Home>
Asynchronous processing with

unity script.
Using the thread class, Video () is executed in the sub thread and RealShadowMove () is executed in the main thread, but when the application is executed by pressing the Play button, the Editor freezes.
Help me if you can tell me why

Applicable source code

The language is C #
`` `Enter the language name here
Source code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;
using OpenCvSharp;
using OpenCvSharp.Blob;
using System;
using System.IO;
public class sdaaasdf: MonoBehaviour
{
private Thread _thread;
private int i = 0;
private Mat gameview;
private Camera ConvertCamera;
private Vector3 ScreenPt = new Vector3 (0f, 0f, 0f);
private Vector3 WorldPoint;
private Vector3 MousePoint;
void Start ()
{
ConvertCamera = Camera.main;
_thread = new Thread (Video);
_thread.Start ();
_thread.Join ();
RealShadowMove ();
}

void Video ()
{
var frame = new Mat ();
var frame2 = new Mat ();
var gray = new Mat ();
var gray2 = new Mat ();
var binary = new Mat ();
var binary2 = new Mat ();
var diff = new Mat ();
var find = new Mat ();
var contours = new Mat [] {};
var hierarchy = new Mat ();
var contours2 = new Mat [] {};
var video0 = new VideoCapture (0);

// var video1 = new VideoCapture (1);
while (true)
{
// Web camera image reading
video0.Read (frame);
// Image processing
binary = ImageProcessing (frame, 180);
// Execute labeling (excludes areas other than necessary)
CvBlobs blobs = new CvBlobs (binary);
blobs.FilterByArea (2000, 7000);
for (int i = 1;i {
var cvContour = blobs [i] .Contour;
var L = cvContour.Perimeter ();
var area = blobs [i] .Area;
var circularity = 4 * Math.PI * (area/(L * L));
if (0.4 {
blobs.FilterByLabel (i);
Debug.Log (circularity);
}
}
// Drawing the labeling results
var render = new Mat (frame.Rows, frame.Cols, MatType.CV_8UC3, 3);
blobs.RenderBlobs (frame, render);

// Crop
CvBlob maxBlob = blobs.LargestBlob ();
render = render [maxBlob.Rect];

// Webcam image processing so far

// Game view image processing in the same way
binary2 = ImageProcessing (gameview, 50);
CvBlobs blobs2 = new CvBlobs (binary2);
var render2 = new Mat (gameview.Rows, gameview.Cols, MatType.CV_8UC3, 3);
blobs2.RenderBlobs (gameview, render2);
CvBlob maxBlob2 = blobs2.LargestBlob ();
render2 = render2 [maxBlob2.Rect];

// Image scaling
Cv2.Resize (render, render, new OpenCvSharp.Size (render2.Width, render2.Height), 0, 0, InterpolationFlags.Cubic);

// Image difference calculation
Cv2.Absdiff (render, render2, diff);

// Effect recognition
var binarydiff = ImageProcessing (diff, 150);
CvBlobs diffblobs = new CvBlobs (binarydiff);
var maxdiffblob = diffblobs.LargestBlob ();
// var realshadow = diff [maxBlob.Rect];
// Bounding box drawing
binarydiff.FindContours (out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone);
for (int i = 0;i {
var Rect = Cv2.BoundingRect (contours [i]);
Cv2.Rectangle (binarydiff, new Point (Rect.X, Rect.Y), new Point (Rect.X + Rect.Width, Rect.Y + Rect.Height), Scalar.Blue, 2);
}
// Coefficient calculation for ratio conversion
var TransportWidth = (double) (Screen.width/binarydiff.Width);
var TransportHeight = (double) (Screen.height/binarydiff.Height);

Debug.Log ("Width ratio:" + TransportWidth);
Debug.Log ("Height ratio:" + TransportHeight);
Debug.Log (maxdiffblob.Area);
if (maxdiffblob.Area>10000)
{
var pt = maxdiffblob.Centroid;
Debug.Log ("actual coordinates" + pt.X + "," + pt.Y);
ScreenPt = new Vector3 ((float) (pt.X * TransportWidth), (float) (Screen.height-(pt.Y * TransportHeight)), 10.0f);
}
else
{
ScreenPt = new Vector3 (-100f, -100f, -100f);
Debug.Log ("aaa");
}

// Display results
using (new Window ("binary", binary));
using (new Window ("render", render));
using (new Window ("render2", render2));
using (new Window ("diff", diff));
using (var win = new Window ("binarydiff", binarydiff));

// using (new Window ("realshadow", realshadow));

// Key input processing
int key = Cv2.WaitKey (100);
if (key == 27) break;
if (i == 1)
{
break;
}
}
}
// Image processing function (argument is image, threshold k (0 ~ 255))
Mat ImageProcessing (Mat frame, int k)
{
var render = new Mat (frame.Rows, frame.Cols, MatType.CV_8UC3, 3);
var gray = new Mat ();
var binary = new Mat ();
// Grayscale conversion
Cv2.CvtColor (frame, gray, ColorConversionCodes.BGR2GRAY);
// Smoothing
Cv2.Blur (gray, gray, new Size (5, 5));
// binarization
binary = gray.Threshold (k, 255, ThresholdTypes.Binary);
return binary;
}

// Move and draw a real object
void RealShadowMove ()
{
while (true)
{
ScreenCapture.CaptureScreenshot ("image4.png");
gameview = new Mat (@ "image.png");
Vector3 MousePos = Input.mousePosition;
MousePos.z = 10.0f;
Debug.Log ("Mouse position" + MousePos);
Debug.Log ("screen coordinates on screen" + ScreenPt);
WorldPoint = ConvertCamera.ScreenToWorldPoint (ScreenPt);
MousePoint = ConvertCamera.ScreenToWorldPoint (MousePos);
WorldPoint.y * = -1;
MousePoint.y * = -1;
//this.gameObject.transform.position = MousePoint;
this.gameObject.transform.position = WorldPoint;
iTween.MoveTo (this.gameObject, WorldPoint, (float) 0.1);
Debug.Log ("real world coordinates" + WorldPoint);
Debug.Log ("Mouse world coordinates" + MousePoint);
if (i == 1)
{
break;
}
}
}
// Update is called once per frame
void Update () {}

private void OnApplicationQuit ()
{
if (_thread! = null)
{
i = 1;
}
}
}

I think that there is a high possibility that an infinite loop has occurred in the while portion, so I tried to get out with keystrokes, but it doesn't work

Supplemental information (FW/tool version etc.)

OS: win10, Unity: 2018.2.2f1
Please include more detailed information here.

  • Answer # 1

    First isolate the problem. For example, do not call RealShadowMove, move only Thread, or vice versa.
    Well, this time I think RealShadowMove is the cause. (Since the Thread side does not read properly, "both" may be the cause)


    There is no part where the variableiis 1, so RealShadowMove's while loops infinitely.

    Even if you put a function to stop with the key, it will freeze at the speed that the CPU allows, so it will probably freeze.
    In the first place, Start does not end until RealShadowMove ends, so Update does not start, soInput. ~is not updated.

    Therefore, you need to either "RealShadowMove as a coroutine and insertyield return null;in while" or "Delete while and call from Update instead of Start" I think.
    (In either case, it will be a "process every frame")