/// <summary> /// Updates list of tracks based on current blobs. /// </summary> /// <param name="blobs">List of blobs</param> /// <param name="thDistance">Distance Max distance to determine when a track and a blob match</param> /// <param name="thInactive">Inactive Max number of frames a track can be inactive</param> /// <param name="thActive">Active If a track becomes inactive but it has been active less than thActive frames, the track will be deleted.</param> public void Update(CvBlobs blobs, double thDistance, uint thInactive, uint thActive) { CvInvoke.cvbCvUpdateTracks(blobs, _ptr, thDistance, thInactive, thActive); }
public static WriteableBitmap DrawBlobBoundingBoxsCV(WriteableBitmap writeableBitmap, WriteableBitmap gradientBitmapRef, WriteableBitmap realBitmapRef) { Bitmap normalBitmap = BitmapFromWriteableBitmap(writeableBitmap); var cvImage = new Image<Gray, byte>(new Bitmap(normalBitmap)); //var classifications = ClassifyBitmap( writeableBitmap, cvImage ); if (cvImage != null) { // This takes our nice looking color png and converts it to black and white Image<Gray, byte> greyImg = cvImage.Convert<Gray, byte>(); // We again threshold it based on brightness...BUT WE INVERT THE PNG. BLOB DETECTOR DETECTS WHITE NOT BLACK // this will esentially eliminate the color differences // you could also do cool things like threshold only certain colors here for a color based blob detector Image<Gray, Byte> greyThreshImg = greyImg.ThresholdBinaryInv(new Gray(150), new Gray(255)); Emgu.CV.Cvb.CvBlobs resultingImgBlobs = new Emgu.CV.Cvb.CvBlobs(); Emgu.CV.Cvb.CvBlobDetector bDetect = new Emgu.CV.Cvb.CvBlobDetector(); uint numWebcamBlobsFound = bDetect.Detect(greyThreshImg, resultingImgBlobs); // This is a simple way of just drawing all blobs reguardless of their size and not iterating through them // It draws on top of whatever you input. I am inputting the threshold image. Specifying an alpha to draw with of 0.5 so its half transparent. //Emgu.CV.Image<Bgr, byte> blobImg = bDetect.DrawBlobs(webcamThreshImg, resultingWebcamBlobs, Emgu.CV.Cvb.CvBlobDetector.BlobRenderType.Default, 0.5); // Here we can iterate through each blob and use the slider to set a threshold then draw a red box around it Image<Rgb, byte> blobImg = greyThreshImg.Convert<Rgb, byte>(); Rgb red = new Rgb(255, 0, 0); int blobNumber = 0; // Lets try and iterate the blobs? foreach (Emgu.CV.Cvb.CvBlob targetBlob in resultingImgBlobs.Values) { int imageArea = blobImg.Width*blobImg.Height; int blobArea = targetBlob.Area; int blobBoundingBoxArea = targetBlob.BoundingBox.Width*targetBlob.BoundingBox.Height; // Only use blobs with area greater than some threshold // If the blob bounding rect is basically size of the whole image ignore it for now if (blobArea > 200.0 && blobBoundingBoxArea < (imageArea*0.99)) { Rectangle rectangle = targetBlob.BoundingBox; int CentroidX = (int)targetBlob.Centroid.X; int CentroidY = (int)targetBlob.Centroid.Y; int croppedWidth = rectangle.Width + 50; int croppedHeight = rectangle.Height + 50; int CroppedX = CentroidX - (int)(croppedWidth / 2.0); int CroppedY = CentroidY - (int)(croppedHeight / 2.0); var croppedBlobBitmap = writeableBitmap.Crop(CroppedX, CroppedY, croppedWidth, croppedHeight); var croppedGradientBlobBitmap = gradientBitmapRef.Crop(CroppedX, CroppedY, croppedWidth, croppedHeight); var croppedRealBitmapRef = realBitmapRef.Crop(CroppedX, CroppedY, croppedWidth, croppedHeight); double blobAngle = -RadianToDegree(CalculateBlobAngle(targetBlob)); CroppedX = (int) (croppedWidth/2.0); CroppedY = (int) (croppedHeight/2.0); var rotatedandCroppedBlobBitmap = RotateWriteableBitmap(croppedBlobBitmap, blobAngle); var rotatedGradientBlobBitmap = RotateColorWriteableBitmap(croppedGradientBlobBitmap, blobAngle); var rotatedRealBitmapRef = RotateColorWriteableBitmap(croppedRealBitmapRef, blobAngle); var refinedBitmap = DrawBlobBoundingBoxsAroundCroppedBitmap(rotatedandCroppedBlobBitmap, rotatedGradientBlobBitmap, rotatedRealBitmapRef, 1); rotatedGradientBlobBitmap = DrawBlobBoundingBoxsAroundCroppedBitmap(rotatedandCroppedBlobBitmap, rotatedGradientBlobBitmap, rotatedRealBitmapRef, 2); rotatedRealBitmapRef = DrawBlobBoundingBoxsAroundCroppedBitmap(rotatedandCroppedBlobBitmap, rotatedGradientBlobBitmap, rotatedRealBitmapRef, 3); var areaCheck = refinedBitmap.PixelHeight*refinedBitmap.PixelWidth; if (areaCheck >= 200) { blobNumber++; var thresholded = refinedBitmap.Clone(); ThresholdBitmap(thresholded, 10, false); BitmapColorer.ColorBitmap(thresholded); System.Windows.Media.Color blobColor = PixelColorOfCentralBlob(thresholded); BitmapColorer.EraseAllButCertainColorandWhite(thresholded, blobColor); var shouldFlip = shouldFlipThresholdedBitmap(thresholded, blobColor); if (shouldFlip) { thresholded = thresholded.Rotate(180); rotatedGradientBlobBitmap = rotatedGradientBlobBitmap.Rotate(180); rotatedRealBitmapRef = rotatedRealBitmapRef.Rotate(180); } var orientedBitmap = NormalizeBitmapSize(thresholded); var orientedGradientBitmap = NormalizeBitmapSize(rotatedGradientBlobBitmap); var orientedRealBitmap = NormalizeBitmapSize(rotatedRealBitmapRef); ApplyBlobMaskToOtherBitmaps(orientedBitmap, orientedGradientBitmap, orientedRealBitmap, blobColor); string fileName1 = saveDirectory + "\\croppedBlob" + blobNumber + ".png"; ExtensionMethods.Save(orientedRealBitmap, fileName1); } } } } return writeableBitmap; }
/// <summary> /// 图漾粗略找合适的轮廓 /// </summary> /// <param name="point_3d">三维点</param> public static void getContours(float[] point_3d) { GLB.TitleStr = ""; int AREA = GLB.BUFW * GLB.BUFH; //总面积 var gray = GLB.MyFrame.Convert <Gray, Byte>(); //灰度化 Emgu.CV.Cvb.CvBlobs myBlobs = new Emgu.CV.Cvb.CvBlobs(); Emgu.CV.Cvb.CvBlobDetector bd = new Emgu.CV.Cvb.CvBlobDetector(); uint n = bd.Detect(gray, myBlobs);//发现区块 ////遍历各区块: for (uint i = 1; i <= myBlobs.Count; i++) { int area = myBlobs[i].Area; //获取面积 RotatedRect rect = CvInvoke.MinAreaRect(new VectorOfPoint(myBlobs[i].GetContour())); //最小矩形 float width = rect.Size.Width; //像素宽 float height = rect.Size.Height; //像素长 if (height < width) { float temp = height; height = width; width = temp; } float H2W = height / width; if (area > 0.02 * AREA && area < 0.75 * AREA && H2W > 1 && H2W < 2)//通过面积 长宽比 初略筛选 { if (getProduceInfo(myBlobs[i], point_3d) == true) { if (ProduceMacth() == true)//匹配成功 { //////#########################################队列求均值--获取中心坐标################################################# //GLB.avgCameraPoint3.Enqueue(new Point3(GLB.camera_device_point.X, GLB.camera_device_point.Y, GLB.camera_device_point.Z)); //if (GLB.avgCameraPoint3.Count > 5) //{ // GLB.avgCameraPoint3.Dequeue(); //} //else //{ // return ; //} //GLB.camera_device_point.Z = (int)GLB.avgCameraPoint3.Average(o => o.Z);//中心点的深度//Z //GLB.camera_device_point.Y = (int)GLB.avgCameraPoint3.Average(o => o.Y);//Y //GLB.camera_device_point.X = (int)GLB.avgCameraPoint3.Average(o => o.X);//X //RotatedRect boxCenter = new RotatedRect(new PointF((float )GLB.obj.jd.Average(o => o.X), (float)GLB.obj.jd.Average(o => o.Y)), new Size(8, 8), 0); //CvInvoke.Ellipse(GLB.MyFrame, boxCenter, new MCvScalar(255, 0, 0), 4);//在中心画一个小圆 //CvInvoke.PutText(GLB.MyFrame, "x:" + (float)GLB.obj.jd.Average(o => o.X) + "y:" + (float)GLB.obj.jd.Average(o => o.Y) + "XC=" + GLB.obj.xCenter + "YC=" + GLB.obj.yCenter + "Depth=" + GLB.obj.Depth, new System.Drawing.Point((int)GLB.obj.jd.Average(o => o.X) - 176, (int)GLB.obj.jd.Average(o => o.Y) + 25), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(255, 255, 255), 2);//深度显示 ////////队列求均值 //GLB.avgAngle.Enqueue((float)GLB.obj.Angle); //if (GLB.avgAngle.Count > 5) //{ // GLB.avgAngle.Dequeue(); //} //else //{ // return ; //} //GLB.obj.Angle = GLB.avgAngle.Average();//旋转角 //CvInvoke.PutText(GLB.MyFrame, "Angl=" + GLB.obj.Angle, new System.Drawing.Point((int)GLB.obj.jd[3].X, (int)GLB.obj.jd[3].Y), Emgu.CV.CvEnum.FontFace.HersheyDuplex, .75, new MCvScalar(0, 0, 255), 2); ////#########################################坐标换算################################################# GLB.robot_device_point.X = GLB.MatTuYangCam[0] * GLB.camera_device_point.X + GLB.MatTuYangCam[1] * GLB.camera_device_point.Y + GLB.MatTuYangCam[2]; GLB.robot_device_point.Y = GLB.MatTuYangCam[3] * GLB.camera_device_point.X + GLB.MatTuYangCam[4] * GLB.camera_device_point.Y + GLB.MatTuYangCam[5]; GLB.robot_device_point.Z = 2818 - GLB.camera_device_point.Z; GLB.device_angl += -2.6f;//相机与机器人夹角2.6度 GLB.device_angl = (float)(GLB.device_angl * Math.PI / 180f); //限定范围 if (GLB.robot_device_point.X < -600 || GLB.robot_device_point.X > 600 || GLB.robot_device_point.Y < -2200 || GLB.robot_device_point.Y > -800 || GLB.robot_device_point.Z < 280 || GLB.robot_device_point.Z > 1100) { GLB.Match_success = false; GLB.TitleStr += ",但是超出范围"; } else { GLB.Match_success = true; } } else { GLB.Match_success = false; } } } } }
public static WriteableBitmap DrawBlobBoundingBoxsAroundCroppedBitmap(WriteableBitmap writeableBitmap, WriteableBitmap gradientBitmapRef, WriteableBitmap realBitmapRef, int returnBitmapIndex) { Bitmap normalBitmap = BitmapFromWriteableBitmap(writeableBitmap); var cvImage = new Image<Gray, byte>(new Bitmap(normalBitmap)); if (cvImage != null) { Image<Gray, byte> greyImg = cvImage.Convert<Gray, byte>(); Image<Gray, Byte> greyThreshImg = greyImg.ThresholdBinaryInv(new Gray(150), new Gray(255)); Emgu.CV.Cvb.CvBlobs resultingImgBlobs = new Emgu.CV.Cvb.CvBlobs(); Emgu.CV.Cvb.CvBlobDetector bDetect = new Emgu.CV.Cvb.CvBlobDetector(); uint numWebcamBlobsFound = bDetect.Detect(greyThreshImg, resultingImgBlobs); Image<Rgb, byte> blobImg = greyThreshImg.Convert<Rgb, byte>(); Rgb red = new Rgb(255, 0, 0); int blobNumber = 0; foreach (Emgu.CV.Cvb.CvBlob targetBlob in resultingImgBlobs.Values) { int imageArea = blobImg.Width*blobImg.Height; int blobArea = targetBlob.Area; int blobBoundingBoxArea = targetBlob.BoundingBox.Width*targetBlob.BoundingBox.Height; if (blobArea > 200.0 && blobBoundingBoxArea < (imageArea*0.99)) { blobNumber++; Rectangle rectangle = targetBlob.BoundingBox; Rect convertedRect = new Rect(rectangle.X - 10, rectangle.Y - 10, rectangle.Width + 20, rectangle.Height + 20); //BitmapColorer.DrawRectangle(writeableBitmap, convertedRect); writeableBitmap = writeableBitmap.Crop(rectangle.X - 10, rectangle.Y - 10, rectangle.Width + 20, rectangle.Height + 20); gradientBitmapRef = gradientBitmapRef.Crop(rectangle.X - 10, rectangle.Y - 10, rectangle.Width + 20, rectangle.Height + 20); realBitmapRef = realBitmapRef.Crop(rectangle.X - 10, rectangle.Y - 10, rectangle.Width + 20, rectangle.Height + 20); } } } if (returnBitmapIndex == 1) { return writeableBitmap; } else if (returnBitmapIndex == 2) { return gradientBitmapRef; } else { return realBitmapRef; } }