首先需要导入emguCV的库并引用
新建Quad,并创建新的材质球,将材质球的Shader改为Unlit/Texture,将材质球赋给Quad。
上代码
//截图时中间的小点
public GameObject hitPoint;
public GameObject hitPointParent;
UdpClient clientSend;
IPEndPoint endpointSend;
//Quad
public GameObject myPlan_L;
UdpClient client;
IPEndPoint endpoint;
Thread t;
string receiveMsg;
public bool saveFinsh;
VideoCapture cap;
Mat frame;
Mat bgImg;
Mat result_D = new Mat();
Mat diff = new Mat();
//Mat ROI_D;
Thread t_V;
public int shootNumber_L;
//灰度值
byte grayValue;
public CombatController combatController;
/// <summary>
/// 是否被击中
/// </summary>
private bool isHit;
private int temp =1;
void Start()
{
bgImg = new Mat();
frame = new Mat();
///视频帧差法检测运动物体
cap = new VideoCapture(0);
cap.SetCaptureProperty(CapProp.FrameWidth, 1920);
cap.SetCaptureProperty(CapProp.FrameHeight, 1080);
clientSend = new UdpClient(new IPEndPoint(IPAddress.Any, 0));
_tex2D = new Texture2D(1920, 1080);//初始化了一个新的2d tex 会占用内存
client = new UdpClient(new IPEndPoint(IPAddress.Any, 6001));
endpoint = new IPEndPoint(IPAddress.Any, 0);
t = new Thread(Socket_rend);
t.IsBackground = true;
t.Start();
t_V = new Thread(OpenCameraVideo);
t_V.IsBackground = true;
t_V.Start();
}
//socket接收接口
void Socket_rend()
{
while (true)
{
byte[] buf = client.Receive(ref endpoint);
receiveMsg = Encoding.Default.GetString(buf);
//print(receiveMsg);
}
}
Mat MoveDetect(Mat bgImg, Mat fgImg)
{
Mat result = fgImg.Clone();
Mat gray = new Mat();
Mat gray2 = new Mat();
CvInvoke.CvtColor(bgImg, gray, ColorConversion.Bgr2Gray);
CvInvoke.CvtColor(fgImg, gray2, ColorConversion.Bgr2Gray);
//做差
CvInvoke.AbsDiff(gray, gray2, diff);
//CvInvoke.Imshow("diff", diff);
//二值化
CvInvoke.Threshold(diff, diff, 50, 255, ThresholdType.Binary);
//CvInvoke.Imshow("threshold", diff);
//中值滤波
CvInvoke.MedianBlur(diff, diff, 5);
//CvInvoke.Imshow("median blur", diff);
//膨胀
Mat element = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(9, 9), new Point(-1, -1));
CvInvoke.Dilate(diff, diff, element, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
//CvInvoke.Imshow("dilate", diff);
//绘制外接椭圆
//VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//CvInvoke.FindContours(diff, contours, null, RetrType.External, ChainApproxMethod.ChainApproxNone);
//for (int i = 0; i < contours.Size; i++)
//{
// RotatedRect rotatedRect = CvInvoke.FitEllipse(contours[i]); //计算外接椭圆
// Point rcenter = new Point((int)rotatedRect.Center.X, (int)rotatedRect.Center.Y);
// CvInvoke.Ellipse(result, rcenter, new Size((int)(rotatedRect.Size.Width / 2), (int)(rotatedRect.Size.Height / 2)), rotatedRect.Angle, 0, 360,
// new MCvScalar(0, 0, 255), 2);
// //Rectangle rect = CvInvoke.BoundingRectangle(contours[i]);
// //CvInvoke.Rectangle(result, rect, new MCvScalar(0, 0, 255), 2);
//}
return result;
}
//截图并保存
void PrintScreen(Mat img, string coords,int shootNumber, Mat threshold)
{
//print("我进来了");
//获取传过来的坐标值
string[] str = DisposeString(coords);
//Console.WriteLine(y);
int x = int.Parse(str[1]);
int y = int.Parse(str[2]);
if (x < 50 || x > 1870 || y < 50 || y > 1030)
{
return;
}
//根据坐标值截图 图片起始位置与大小
Mat ROI = new Mat(img, new Rectangle(x - 50, 1080 - y - 50, 100, 100));
//print(x +" "+ y);
//CvInvoke.Line(ROI, x_P, y_P, new MCvScalar(255, 0, 0), s100, LineType.EightConnected,2);
CvInvoke.Imwrite(Application.dataPath + "/Image/" + str[0] + shootNumber.ToString() + ".png", ROI);
//CvInvoke.Imwrite(Application.dataPath + "result_D.png", img);
Image<Bgr, byte> grayValueImg = threshold.ToImage<Bgr, Byte>();
grayValue = grayValueImg.Data[ x, 1080 - y, 0];
receiveMsg = null;
saveFinsh = true;
//Destroy(temp);
}
private string[] DisposeString(string msg)
{
string[] str = null;
if (msg != null)
{
str = msg.Split('/');
}
return str;
}
void OpenCameraVideo()
{
if (!cap.IsOpened)
{
print("Open video failed..");
return;
}
int count = 0;
while (true)
{
cap.Read(frame);
if (frame.IsEmpty)
{
print("frame is empty..");
break;
}
count++;
if (count == 1)
{
bgImg = frame.Clone();
}
//String y = Socket_rend();
//if (y != null)
//{
// PrintScreen(frame.Clone(), y);
//}
result_D = MoveDetect(bgImg, frame);
//CvInvoke.Imshow("move", result_D);
//bgImg = frame.Clone(); //更新前一帧
CvInvoke.WaitKey(30);
if (CvInvoke.WaitKey(30) == 27)
{
break;
}
}
}
Texture2D _tex2D;
/// <summary>
/// 不断刷新纹理,制造视频效果
/// </summary>
void FileStreamLoadTexture(Mat myMat)
{
//Mat src = CvInvoke.Imread(Application.dataPath + "/StreamingAssets/new.png", ImreadModes.Unchanged);
Image<Bgr, byte> img = myMat.ToImage<Bgr, Byte>();
_tex2D.LoadImage(img.ToJpegData());
_tex2D.Apply();
myPlan_L.GetComponent<MeshRenderer>().material.mainTexture = _tex2D;
//Destroy(_tex2D);// 释放掉2d tex的内存占用 注释掉可以看到画面贴图切换的效果
}
private void Update()
{
if (result_D != null)
{
if (Time.frameCount % 2 == 0)
{
try
{
FileStreamLoadTexture(result_D);
}
catch
{
}
}
}
if (receiveMsg != null && receiveMsg.Substring(0,1) == "l")
{
if (shootNumber_L < combatController.totalBulletNum)
{
shootNumber_L += 1;
PrintScreen(result_D, receiveMsg, shootNumber_L,diff);
if (grayValue > 245)
{
SendToSerial();//向硬件发送被击中的消息
isHit = true;
}
else
{
isHit = false;
}
combatController.Fire_L(isHit, "l" + shootNumber_L);//左侧玩家开火
}
}
if (Input.GetKeyDown(KeyCode.S))
{
PrintScreen(result_D, "l/500/500", temp,diff);
combatController.Fire_L(isHit, "l" + temp);
temp++;
}
if (Input.GetKeyDown(KeyCode.Escape))
{
endpointSend = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 53478);
byte[] buf = Encoding.Default.GetBytes("Quit");
clientSend.Send(buf, buf.Length, endpointSend);
}
}
public void SendToSerial()
{
endpointSend = new IPEndPoint(IPAddress.Parse("255.255.255.255"), 53478);
byte[] buf = Encoding.Default.GetBytes("32");
clientSend.Send(buf, buf.Length, endpointSend);
grayValue = 0;
}
|