/// <summary> /// Get a copy of the data values as an array /// </summary> /// <param name="jagged">If true, a jagged array will returned. Otherwise it will return a regular array.</param> /// <returns>a copy of the data values as an array</returns> public Array GetData(bool jagged = true) { using (InputArray iaM = this.GetInputArray()) using (Mat m = iaM.GetMat()) { return(m.GetData(jagged)); } }
public static void FindMatch(Mat modelImage, Mat observedImage, out long matchTime, out VectorOfKeyPoint modelKeyPoints, out VectorOfKeyPoint observedKeyPoints, VectorOfVectorOfDMatch matches, out Mat mask, out Mat homography, out long score) { int k = 2; double uniquenessThreshold = 0.80; Stopwatch watch; homography = null; modelKeyPoints = new VectorOfKeyPoint(); observedKeyPoints = new VectorOfKeyPoint(); using (UMat uModelImage = modelImage.GetUMat(AccessType.Read)) using (UMat uObservedImage = observedImage.GetUMat(AccessType.Read)) { KAZE featureDetector = new KAZE(); Mat modelDescriptors = new Mat(); featureDetector.DetectAndCompute(uModelImage, null, modelKeyPoints, modelDescriptors, false); watch = Stopwatch.StartNew(); Mat observedDescriptors = new Mat(); featureDetector.DetectAndCompute(uObservedImage, null, observedKeyPoints, observedDescriptors, false); // KdTree for faster results / less accuracy using (var ip = new Emgu.CV.Flann.KdTreeIndexParams()) using (var sp = new SearchParams()) using (DescriptorMatcher matcher = new FlannBasedMatcher(ip, sp)) { matcher.Add(modelDescriptors); matcher.KnnMatch(observedDescriptors, matches, k, null); mask = new Mat(matches.Size, 1, DepthType.Cv8U, 1); mask.SetTo(new MCvScalar(255)); Features2DToolbox.VoteForUniqueness(matches, uniquenessThreshold, mask); // Calculate score based on matches size // ----------------------------------------------> score = 0; for (int i = 0; i < matches.Size; i++) { if (mask.GetData(i)[0] == 0) { continue; } foreach (var e in matches[i].ToArray()) { ++score; } } // <---------------------------------------------- int nonZeroCount = CvInvoke.CountNonZero(mask); if (nonZeroCount >= 4) { nonZeroCount = Features2DToolbox.VoteForSizeAndOrientation(modelKeyPoints, observedKeyPoints, matches, mask, 1.5, 20); if (nonZeroCount >= 4) { homography = Features2DToolbox.GetHomographyMatrixFromMatchedFeatures(modelKeyPoints, observedKeyPoints, matches, mask, 2); } } } watch.Stop(); } matchTime = watch.ElapsedMilliseconds; }
public static byte[] Canny(IntPtr buffer, int width, int height, bool smooth = false) { unsafe { Mat source = new Mat(height, width, DepthType.Cv8U, 1, buffer, width); Mat blurred = new Mat(height, width, DepthType.Cv8U, 1); if (smooth) { CvInvoke.Blur(source, blurred, new Size(3, 3), new Point(-1, -1)); } Mat cannyEdges = new Mat(height, width, DepthType.Cv8U, 1); double cannyThreshold = 180.0; double cannyThresholdLinking = 60.0; CvInvoke.Canny(smooth ? blurred : source, cannyEdges, cannyThreshold, cannyThresholdLinking); return cannyEdges.GetData(); } }
//Transform images according to transform matrix // From Line 130-239 public static ReturnColorImg transformColor(Mat img1, Mat mask1, Mat img2, Mat mask2, Mat dst, Mat dst_mask, Point centroid1, Point centroid2, double angle, Point tweak1, Point tweak2, bool mode = true) { Mat E = img2.Clone(); Mat E_mask = mask2.Clone();//Don't ruin original images double intersections = 0; double x = centroid2.X; double y = centroid2.Y; double _x, _y, _y2; double y2; LineSegment2D centerLine = new LineSegment2D(new Point((int)x, (int)y), new Point(img2.Width - (int)x, img2.Height - (int)y)); //Rectangle r=new Rectangle((int)x,(int)y,2*(img2.Width-(int)x),2*(img2.Height-(int)y)); Mat ri = new Mat(2 * (img2.Width - (int)x), 2 * (img2.Height - (int)y),DepthType.Cv8U, 3); ri.SetTo(new MCvScalar(255, 255, 255)); Point oldc = new Point((int)x, (int)y); bool success = false; // if the tweaking is not successful, return false // inverse y axis // y2 = -y; // rotation of centeroid x -= img2.Width / 2; y -= img2.Height / 2;//shift origin to (w/2,h/2) _x = x * Math.Cos(angle / (180 / Math.PI)) - y * Math.Sin(angle / (180 / Math.PI));//rotate by theta _y = x * Math.Sin(angle / (180 / Math.PI)) + y * Math.Cos(angle / (180 / Math.PI)); _x += img2.Width / 2; _y += img2.Height / 2;//back to origin //_x = x+img2.Width/2; //_y = y+img2.Height/2; // inverse y axis //_y = -_y2; centroid2.X = (int)_x; centroid2.Y = (int)_y; Point shift = new Point(); shift.X = centroid1.X - centroid2.X; shift.Y = centroid1.Y - centroid2.Y; MatImage m1 = new MatImage(E); m1.Rotate(angle, new Bgr(255, 255, 255)); E = m1.Out(); MatImage m2 = new MatImage(E_mask); m1.Rotate(angle, new Bgr(255, 255, 255)); E_mask = m2.Out(); //Find optimal size of canvas to hold both images and appropriate transformations Point t1, t2;//transformation 1 and 2 t1 = new Point(); t2 = new Point(); int optimal_h = 0, optimal_w = 0;//of canvas(IplImage* dst) switch (quadrant(shift)) { case 1: t1.X = 0; t1.Y = 0; t2 = shift; optimal_h = Math.Max(img1.Height, img2.Height + shift.Y); optimal_w = Math.Max(img1.Width, img2.Width + shift.X); break; case 2: t1.X = -shift.X; t1.Y = 0; t2.X = 0; t2.Y = shift.Y; optimal_h = Math.Max(img1.Height, img2.Height + shift.Y); optimal_w = Math.Max(img2.Width, img1.Width - shift.X); break; case 3: t1.X = -shift.X; t1.Y = -shift.Y; t2.X = 0; t2.Y = 0; optimal_h = Math.Max(img1.Height - shift.Y, img2.Height); optimal_w = Math.Max(img1.Width - shift.X, img2.Width); break; case 4: t1.X = 0; t1.Y = -shift.Y; t2.X = shift.X; t2.Y = 0; optimal_h = Math.Max(img1.Height - shift.Y, img2.Height); optimal_w = Math.Max(img2.Width + shift.X, img1.Width); break; } // add tweak factor t1.X += tweak1.X; t1.Y += tweak1.Y; t2.X += tweak2.X; t2.Y += tweak2.Y; //optimal_h = 1000; //optimal_w = 1000; dst = new Mat(optimal_h, optimal_w,DepthType.Cv8U,3); dst_mask = new Mat(optimal_h, optimal_w,DepthType.Cv8U,3); if (mode) { dst.SetTo(new MCvScalar(255, 255, 255)); // white background=255, black background=0 } else { dst.SetTo(new MCvScalar(0, 0, 0)); // white background=255, black background=0 } dst_mask.SetTo(new MCvScalar(0, 0, 0)); /*if (BKG_WHITE) cvSet(dst, cvScalar(255));//make it white else cvSet(dst, cvScalar(0));//make it black*/ for (int i = 0; i < img1.Height; ++i) { for (int j = 0; j < img1.Width; ++j) { // if black background if (mode) { if (mask1.GetData(i, j)[0] != 255) { int i_new = i + t1.Y; int j_new = j + t1.X; try { dst.SetValue(i_new, j_new, img1.GetData(i, j)); int[] vals = { 255, 255, 255 }; dst_mask.SetValue(i_new, j_new, vals); } catch(IndexOutOfRangeException e) { //MessageBox.Show("You cannot tweak in that direction further"); success = false; goto ret; } } } // if white background else { if (mask1.GetData(i, j) [0] != 0) { int i_new = i + t1.Y; int j_new = j + t1.X; try { dst.SetValue(i_new, j_new, img1.GetData(i, j)); int[] vals = { 0, 0, 0 }; dst_mask.SetValue(i_new, j_new, vals); } catch(IndexOutOfRangeException e) { //MessageBox.Show("You cannot tweak in that direction further"); success = false; goto ret; } } } } } //Apply transformation to image2 for (int i = 0; i < img2.Height; ++i) { for (int j = 0; j < img2.Width; ++j) { // if black background if (mode) { if (E_mask.GetData(i, j) [0] != 255) { int i_new = i + t2.Y; int j_new = j + t2.X; try { if (dst_mask.GetData(i_new,j_new)[0] != 0) { intersections++; } else { dst.SetValue(i_new, j_new, E.GetData(i, j)); int[] vals = { 255, 255, 255 }; dst_mask.SetValue(i_new, j_new, vals); } } catch (IndexOutOfRangeException e) { //MessageBox.Show("You cannot tweak in that direction further"); success = false; goto ret; } } } // else if white background else { if (E_mask.GetData(i, j)[0] != 0) { int i_new = i + t2.Y; int j_new = j + t2.X; try { if (dst_mask.GetData(i_new, j_new)[0] != 0) { intersections++; } else { dst.SetValue(i_new, j_new, E.GetData(i, j)); int[] vals = { 0, 0, 0 }; dst_mask.SetValue(i_new, j_new, vals); } } catch (IndexOutOfRangeException e) { //MessageBox.Show("You cannot tweak in that direction further"); success = false; goto ret; } } } } } /*for (int i = 0; i < Adst.Length; i++) { for(int j=0; j < Adst[0].Length; j++) { dst.SetValue(i, j, Adst[i][j]); } } for (int i = 0; i < Adst_mask.Length; i++) { for (int j = 0; j < Adst_mask[0].Length; j++) { dst_mask.SetValue(i, j, Adst_mask[i][j]); } }*/ // dst.SetTo(Adst); //dst_mask.SetTo(Adst_mask); success = true; /*cvReleaseImage(&E); cvReleaseImage(&E_mask);*/ // should not need these two lines because of garbage collection // threshold detection is meaningless for 2-piece case, always success ret: if (intersections > Constants.THRESHOLD) { /*cvReleaseImage(&dst);//In case of failure in joining cvReleaseImage(&dst_mask);//release memory*/ ReturnColorImg img = new ReturnColorImg(); img.img = dst; img.img_mask = dst_mask; img.source1 = img1; img.source2 = E_mask; img.center1 = centroid1; img.center2old = oldc; img.center2new = centroid2; img.centerLinee = centerLine; img.returnbool = false; // for determining if the image is matched or not img.translate1 = t1; img.translate2 = t2; img.overlap = intersections; img.success = success; // for tweak only return img; } else { ReturnColorImg img = new ReturnColorImg(); img.img = dst; img.img_mask = dst_mask; img.source1 = img1; img.source2 = E_mask; img.center1 = centroid1; img.center2old = oldc; img.center2new = centroid2; img.centerLinee = centerLine; img.returnbool = true; // for determining if the image is matched or not img.translate1 = t1; img.translate2 = t2; img.overlap = intersections; img.success = success; // for tweak only return img; } }