Unity 调用dll打开相机并检测运动

C++ / OpenCV / .cpp /

#include<opencv2/opencv.hpp>
using namespace cv;

//..\..\UnityActivate\VSActivateUnity.exe

#define EXPORT_API __declspec(dllexport)

VideoCapture my_camera;
Mat image, imageR, imageL;
int m_width = 640;
int m_height = 480;

Mat background;
int count = 0;

Mat MoveDetect(Mat background, Mat tex)
{
	//将background和img转为灰度图
	Mat result = tex.clone();
	Mat gray1, gray2;
	cvtColor(background, gray1, CV_BGR2GRAY);
	cvtColor(tex, gray2, CV_BGR2GRAY);

	//进行canny边缘检测 
	Canny(background, background, 0, 30, 3);

	//将background和img做差;对差值图diff进行阈值化处理
	Mat diff;
	absdiff(gray1, gray2, diff);
	//imshow("absdiss", diff);
	threshold(diff, diff, 50, 255, CV_THRESH_BINARY);
	//imshow("threshold", diff);

	//腐蚀膨胀消除噪音
	/*
	Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
	Mat element2 = getStructuringElement(MORPH_RECT, Size(15, 15));
	erode(diff, diff, element);
	//imshow("erode", diff);
	dilate(diff, diff, element2);
	//imshow("dilate", diff);
	*/

	//二值化后使用中值滤波+膨胀
	Mat element = getStructuringElement(MORPH_RECT, Size(11, 11));
	medianBlur(diff, diff, 5);//中值滤波
	//imshow("medianBlur", diff);
	dilate(diff, diff, element);
	//blur(diff, diff, Size(10, 10)); //均值滤波
	//imshow("dilate", diff);

	//查找并绘制轮廓
	vector<vector<Point>> contours;
	vector<Vec4i> hierarcy;
	findContours(diff, contours, hierarcy, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE); //查找轮廓
	vector<Rect> boundRect(contours.size()); //定义外接矩形集合
	//drawContours(img2, contours, -1, Scalar(0, 0, 255), 1, 8);  //绘制轮廓

	//查找正外接矩形
	int x0 = 0, y0 = 0, w0 = 0, h0 = 0;
	double Area = 0, AreaAll = 0;
	for (int i = 0; i<contours.size(); i++)
	{
		boundRect[i] = boundingRect((Mat)contours[i]); //查找每个轮廓的外接矩形
		x0 = boundRect[i].x;  //获得第i个外接矩形的左上角的x坐标
		y0 = boundRect[i].y; //获得第i个外接矩形的左上角的y坐标
		w0 = boundRect[i].width; //获得第i个外接矩形的宽度
		h0 = boundRect[i].height; //获得第i个外接矩形的高度

		//计算面积
		double Area = contourArea(contours[i]);//计算第i个轮廓的面积
		AreaAll = Area + AreaAll;

		//筛选
		if (w0>140 && h0>140)
			rectangle(result, Point(x0, y0), Point(x0 + w0, y0 + h0), Scalar(0, 255, 0), 2, 8); //绘制第i个外接矩形

		//文字输出
		Point org(10, 35);
		if (i >= 1 && AreaAll >= 19600)
			putText(result, "Is Blocked ", org, CV_FONT_HERSHEY_SIMPLEX, 0.8f, Scalar(0, 255, 0), 2);

	}
	return result;
}


extern "C" bool  EXPORT_API openCamera()
{
	bool my_open = false;
	while (!my_camera.isOpened())
	{
		//std::cout << "Cannot open the camera!" << std::endl;
		my_camera.open(0);
	}
	my_camera.set(CV_CAP_PROP_FRAME_WIDTH, m_width);
	my_camera.set(CV_CAP_PROP_FRAME_HEIGHT, m_height);
	if (my_camera.isOpened())
	{
		my_open = true;
	}
	return my_open;
}

extern "C" void   EXPORT_API recieveFrame(uchar* texturePtr)
{

	Mat my_frameBGR;
	Mat my_frameRBG;
	Mat result;

	my_camera >> my_frameBGR;
	if (my_frameBGR.data)
	{
		cvtColor(my_frameBGR, my_frameRBG, CV_BGR2RGB);
		memcpy(texturePtr, my_frameRBG.data, my_frameRBG.cols*my_frameRBG.rows*my_frameRBG.channels()*sizeof(uchar));

		count++;
		if (count == 1)
			background = my_frameBGR.clone();
		result = MoveDetect(background, my_frameBGR);
		imshow("result", result);

	}

}

extern "C" void EXPORT_API closeCamera()
{
	if (my_camera.isOpened())
	{
		my_camera.release();
	}
}

Unity / C# 

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;//用c++中dll文件需要引入  

public class IsOrNoDll: MonoBehaviour
{

    [DllImport("YesOrNoDll")]
    public static extern bool openCamera();

    [DllImport("YesOrNoDll")]
    public static extern void recieveFrame(byte[] imageData);

    [DllImport("YesOrNoDll")]
    public static extern void closeCamera();

    public bool IsOpen = false;
    public byte[] imageData;
    public Texture2D tex;
    public Texture2D background;
    public int Width = 640;
    public int Length = 480;

    // Use this for initialization
    void Start()
    {
        //open one camera
        IsOpen = openCamera();
        if (IsOpen)
        {
            imageData = new byte[Length * Width * 3];
            tex = new Texture2D(Width, Length, TextureFormat.RGB24, false);

            background = new Texture2D(Width, Length, TextureFormat.RGB24, false);
            recieveFrame(imageData);
            background.LoadRawTextureData(imageData);
            background.Apply();
            GetComponent<Renderer>().material.mainTexture = background;
        }

    }

    // Update is called once per frame
    void Update()
    {

        //update one camera
        if (IsOpen)
        {
            recieveFrame(imageData);
            tex.LoadRawTextureData(imageData);
            tex.Apply();
            GetComponent<Renderer>().material.mainTexture = tex;

        }
    }


    void OnGUI()
    {
        if (!IsOpen)
        {
            //string myword = "打开相机失败!";
            string myword = "camera pause for a while!";
            GUI.TextArea(new Rect(200, 100, 200, 50), myword, new GUIStyle());
        }
        //to get the button
        GUI.color = Color.yellow;
        GUI.backgroundColor = Color.red;
        if (GUI.Button(new Rect(40, 50, 60, 30), "continue"))
        {
            IsOpen = true;
        }

        GUI.color = Color.white;
        GUI.backgroundColor = Color.green;
        if (GUI.Button(new Rect(40, 100, 60, 30), "pause"))
        {
            IsOpen = false;
        }

        GUI.color = Color.white;
        GUI.backgroundColor = Color.blue;
        if (GUI.Button(new Rect(40, 150, 60, 30), "close"))
        {
            closeCamera();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/KillMeHealMe/article/details/88424734