public IplImage BitwiseMat(IplImage src) { Mat Input1 = new Mat(src); Mat Input2 = new Mat(this.Binary(src, 150)); Mat bitwise = new Mat(); Window win_src1 = new Window("src1", WindowMode.StretchImage, Input1); Window win_src2 = new Window("src2", WindowMode.StretchImage, Input2); Cv2.BitwiseNot(Input1, bitwise); Window win_Not = new Window("BitwiseNot", WindowMode.StretchImage, bitwise); Cv2.BitwiseAnd(Input1, Input2.CvtColor(ColorConversion.GrayToBgr), bitwise); Window win_And = new Window("BitwiseAnd", WindowMode.StretchImage, bitwise); Cv2.BitwiseOr(Input1, Input2.CvtColor(ColorConversion.GrayToBgr), bitwise); Window win_Or = new Window("BitwiseOr", WindowMode.StretchImage, bitwise); Cv2.BitwiseXor(Input1, Input2.CvtColor(ColorConversion.GrayToBgr), bitwise); Window win_Xor = new Window("BitwiseXor", WindowMode.StretchImage, bitwise); //IplImage 형식// //Cv.Not(); //Cv.And(); //Cv.Or(); //Cv.Xor(); //IplImage 형식// return(Input2.ToIplImage()); }
public void Bitwise() { const int count = 256; var random = new Random(0); var array1 = Enumerable.Range(0, count).Select(i => (byte)i).OrderBy(_ => random.Next()).ToArray(); var array2 = Enumerable.Range(0, count).Select(i => (byte)i).OrderBy(_ => random.Next()).ToArray(); using var mat1 = new Mat(count, 1, MatType.CV_8UC1, array1); using var mat2 = new Mat(count, 1, MatType.CV_8UC1, array2); using var and = new Mat(); using var or = new Mat(); using var xor = new Mat(); using var not = new Mat(); Cv2.BitwiseAnd(mat1, mat2, and); Cv2.BitwiseOr(mat1, mat2, or); Cv2.BitwiseXor(mat1, mat2, xor); Cv2.BitwiseNot(mat1, not); for (int i = 0; i < count; i++) { Assert.Equal((byte)(array1[i] & array2[i]), and.Get <byte>(i)); Assert.Equal((byte)(array1[i] | array2[i]), or.Get <byte>(i)); Assert.Equal((byte)(array1[i] ^ array2[i]), xor.Get <byte>(i)); Assert.Equal((byte)(~array1[i]), not.Get <byte>(i)); } }
private Mat GetSceleton(Mat grayImage) { var binary = new Mat(); Cv2.Threshold(grayImage, binary, 240, 255, ThresholdType.BinaryInv); var skel = Mat.Zeros(binary.Rows, binary.Cols, MatType.CV_8UC1).ToMat(); var temp = new Mat(binary.Cols, binary.Rows, MatType.CV_8UC1); var elem = Cv2.GetStructuringElement(StructuringElementShape.Cross, new OpenCvSharp.CPlusPlus.Size(3, 3)); bool done; do { Cv2.MorphologyEx(binary, temp, MorphologyOperation.Open, elem); Cv2.BitwiseNot(temp, temp); Cv2.BitwiseAnd(binary, temp, temp); Cv2.BitwiseOr(skel, temp, skel); Cv2.Erode(binary, binary, elem); double max; double min; Cv2.MinMaxLoc(binary, out min, out max); done = (max == 0); } while (!done); return(skel); }
public override bool run() { Mat element = Cv2.GetStructuringElement(MorphShapes.Cross, new Size(3, 3)); Mat skel = Mat.Zeros(src.Size(), MatType.CV_8UC1); Mat erode = Mat.Zeros(src.Size(), MatType.CV_8UC1); Mat temp = Mat.Zeros(src.Size(), MatType.CV_8UC1); int i = 0; Mat im = src.Clone(); int noneZero; do { noneZero = im.CountNonZero(); erode = im.Erode(element); temp = erode.Dilate(element); Cv2.Subtract(im, temp, temp); Cv2.BitwiseOr(skel, temp, skel); erode.CopyTo(im); // Cv2.ImShow("erode", erode); Cv2.WaitKey(); i += 1; } while (im.CountNonZero() > 0 && im.CountNonZero() != noneZero); dst = skel; return(true); }
private void マスク合成(Mat[] src_color, ref Mat dst_color) { foreach (Mat src in src_color) { Cv2.BitwiseOr(src, dst_color, dst_color); } }
static void Update() { //HSV画像とスライダーの値からマスクを生成 var scalar_min = new Scalar(_h_min, _s_min, _v_min); var scalar_max = new Scalar(_h_max, _s_max, _v_max); _src.CopyTo(_mask); if (_h_min < 0) { var tempScalar1 = new Scalar(179, _s_max, _v_max); var tempScalar2 = new Scalar(0, _s_min, _s_min); scalar_min = new Scalar(_h_min + 180, _s_min, _v_min); var masks = new List <Mat>(); masks.Add(CreateMaskImage(_src, scalar_min, tempScalar1)); masks.Add(CreateMaskImage(_src, tempScalar2, scalar_max)); Cv2.BitwiseOr(masks[0], masks[1], _mask); } else { Cv2.InRange(_hsv, scalar_min, scalar_max, _mask); } //画像前処理をする //PreProcessing(); Cv2.ImShow(WINDOW_NAME, _mask); ////マスク画像を使って元画像にフィルタをかける //_dst = new Mat(); ////src.CopyTo(src, mask); //Cv2.BitwiseAnd(_src, _src, _dst, _mask); //ウィンドウの画像を更新 _src.CopyTo(_dst); int HueToDisplay(int hue) { return(hue + 180); } int SatValToDisplay(int aaa) { return((int)(aaa / 2.55)); } Cv2.PutText(_dst, $"Hue: {HueToDisplay(_h_min)} ~ {HueToDisplay(_h_max)}", new Point(20, 20), HersheyFonts.HersheyTriplex, fontScale: 1.5, Scalar.Red, thickness: 2); Cv2.PutText(_dst, $"Sat: {SatValToDisplay(_s_min)} ~ {SatValToDisplay(_s_max)}", new Point(20, 70), HersheyFonts.HersheyTriplex, fontScale: 1.5, Scalar.Red, thickness: 2); Cv2.PutText(_dst, $"Val: {SatValToDisplay(_v_min)} ~ {SatValToDisplay(_v_max)}", new Point(20, 120), HersheyFonts.HersheyTriplex, fontScale: 1.5, Scalar.Red, thickness: 2); Cv2.ImShow("src", _dst); }
public override void Update( ) { Mat blueMask = Source.HsvImage.InRange(SpriteBlueLowerMask, SpriteBlueUpperMask); Mat greenMask = Source.HsvImage.InRange(SpriteGreenLowerMask, SpriteGreenUpperMask); Cv2.BitwiseOr(blueMask, greenMask, Mask); Mask = Mask.Dilate(null, iterations: 4); Mask = Mask.MorphologyEx(MorphTypes.Close, null, iterations: 3); Mask = Mask.Erode(null, iterations: 4); }
private void bn_LogicalSum_Click(object sender, RoutedEventArgs e) { if (listImage.Count > 0) { SubWindow.Win_LogicalSum win = new SubWindow.Win_LogicalSum(listImage); if (win.ShowDialog() == true) { int nMode = win.nMode; int nIdx1 = win.nSrc1; int nIdx2 = win.nSrc2; Mat matSrc1 = listImage[nIdx1].fn_GetImage(); Mat matSrc2 = listImage[nIdx2].fn_GetImage(); Mat matDst = new Mat(); timeStart = DateTime.Now; switch (nMode) { case 0: Cv2.Add(matSrc1, matSrc2, matDst); break; case 1: Cv2.Subtract(matSrc1, matSrc2, matDst); break; case 2: //Cv2.Average(matSrc1, matSrc2, matDst); break; case 3: //Cv2.Differential() Cv2.Absdiff(matSrc1, matSrc2, matDst); break; case 4: Cv2.BitwiseAnd(matSrc1, matSrc2, matDst); break; case 5: Cv2.BitwiseOr(matSrc1, matSrc2, matDst); break; } fn_WriteLog($"[Logical Sum] {listImage[nIdx1].Title} + {listImage[nIdx2].Title} : {nMode} ({(DateTime.Now - timeStart).TotalMilliseconds} ms)"); fn_NewImage(matDst, $"Logical Sum {nMode}"); } } }
public override void Update() { Mat brownMask = Source.InversedHsvImage.InRange(PcmacgBrownLowerMask, PcmacgBrownUpperMask); Mat orangeMask = Source.InversedHsvImage.InRange(PcmacgOrangeLowerMask, PcmacgOrangeUpperMask); Mat skinMask = Source.InversedHsvImage.InRange(PcmacgSkinLowerMask, PcmacgSkinUpperMask); Cv2.BitwiseOr(brownMask, orangeMask, Mask); Cv2.BitwiseOr(Mask, skinMask, Mask); Vec3b a = Source.InversedHsvImage.At <Vec3b> (107, 368); Debug.WriteLine($"{a.Item0},{a.Item1},{a.Item2}"); Mask = Mask.Dilate(null, iterations: 5); Mask = Mask.MorphologyEx(MorphTypes.Close, null, iterations: 3); Mask = Mask.Erode(null, iterations: 4); }
public void EdgeDetect(string fileName) { Mat srcMat = Cv2.ImRead(fileName); Mat srcBlue = srcMat.Split()[0]; Mat cannyMat = new Mat(); Mat sobelMat = new Mat(); Mat LaplasMat = new Mat(); Cv2.Canny(srcBlue, cannyMat, 50, 200, 3); //Cv2.ConvertScaleAbs() Cv2.Sobel(srcBlue, sobelMat, sobelMat.Type(), 1, 1, 1); Cv2.Laplacian(srcBlue, LaplasMat, 3); Cv2.ConvertScaleAbs(LaplasMat, LaplasMat, 1, 0); ImShow(srcBlue); ImShow(cannyMat); ImShow(sobelMat); ImShow(LaplasMat); Mat merge = new Mat(srcMat.Size(), MatType.CV_8U); foreach (Mat tm in srcMat.Split()) { Mat tmm = new Mat(); //Cv2.Canny(tm, tmm, 10, 250, 3); Cv2.Laplacian(tm, tmm, 3); Cv2.ConvertScaleAbs(tmm, tmm, 1, 0); ImShow(tmm); Cv2.Threshold(tmm, tmm, 0.5, 255, ThresholdTypes.Binary); Cv2.BitwiseOr(merge, tmm, merge); } Cv2.MorphologyEx(merge, merge, MorphTypes.Erode, Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3), new OpenCvSharp.Point(1, 1))); ImShow(merge); Cv2.WaitKey(); }
/// <summary> /// images内の画像の白部分をORで統合した画像を得る。 /// useOrNotのimagesに対応するインデックスの要素をtrueにすると使用し、falseなら無視する。 /// 例 : useOrNot = {true, true, true, false, false, true} => R, G, B, V を使用する。 /// </summary> public static Bitmap UnionImages(Bitmap[] images, bool[] useOrNot) { // Matに変換 var mat = new Mat[images.Length]; for (int i = 0; i < images.Length; i++) { mat[i] = images[i].ToMat(); } var unionMat = new Mat(mat[0].Height, mat[0].Width, mat[0].Type()); for (int i = 0; i < mat.Length; i++) { if (useOrNot[i]) { Cv2.BitwiseOr(unionMat, mat[i], unionMat); } } return(unionMat.ToBitmap()); }
private void timer1_Tick(object sender, EventArgs e) { src = cap.QueryFrame(); pictureBoxIpl1.ImageIpl = src; if (src == null) { timer1.Stop(); } else { // ? 결과에는 그레이 처리 //using (Gray g = new Gray()) //{ // pictureBoxIpl2.ImageIpl = g.GrayProcess(src); //} Mat img = new Mat(src); Mat img2 = new Mat(src2); Mat converted = new Mat(); Cv2.CvtColor(img, converted, ColorConversion.BgrToHsv); Mat green = converted.Clone(); Cv2.InRange(converted, new Scalar(70 - 10, 30, 30), new Scalar(70 + 10, 255, 255), green); //잘되는거 //Cv2.InRange(converted, new Scalar(70 - 10, 3, 3), new Scalar(70 + 10, 255, 255), green); Mat dst = new Mat(); Mat dst1 = new Mat(); Mat inverted = new Mat(); Cv2.BitwiseNot(green, inverted); Cv2.BitwiseAnd(img, img, dst, inverted); Cv2.BitwiseOr(dst, img2, dst1, green); Cv2.BitwiseOr(dst, dst1, dst1); //pictureBoxIpl2.ImageIpl = dst1.ToIplImage(); pictureBoxIpl2.ImageIpl = dst1.ToIplImage(); } }
/** * 去掉小数点等噪点 */ private static Mat DropSmallAreaNoise(Mat ImgBinary) { var Binary2 = new Mat(); Cv2.BitwiseNot(ImgBinary, Binary2); Point[][] Contours = Cv2.FindContoursAsArray(Binary2, RetrievalModes.External, ContourApproximationModes.ApproxSimple); // 找出面积最大的区域 int MaxArea = 0; foreach (Point[] Contour in Contours) { Rect Region = Cv2.BoundingRect(Contour); var Area1 = Region.Width * Region.Height; if (Area1 > MaxArea) { MaxArea = Area1; } } // 构造图像掩码 Mat MaskMat = Mat.Zeros(Binary2.Rows, Binary2.Cols, MatType.CV_8UC1); foreach (Point[] Contour in Contours) { Rect Region = Cv2.BoundingRect(Contour); var Area1 = Region.Width * Region.Height; if (Region.Height > Region.Width && (0.0 + Region.Height) / Region.Width < 3 && Area1 * 4 < MaxArea) { // 设置感兴趣区域为纯白色(假定白色为背景色) MaskMat[Region].SetTo(new Scalar(255)); } } var Result = new Mat(); Cv2.BitwiseOr(ImgBinary, MaskMat, Result); return(Result); }
Mat getBackgroundMask(Mat input) { Mat[] backMask = new Mat[4]; Mat backMaskfin = new Mat(); Mat dilate = new Mat(); /*Cv2.InRange( * input, * new Scalar(bHueL[0], bSatL[0], bvalL[0]), * new Scalar(bHueH[0], bSatH[0], bvalH[0]), * backMask1);*/ for (int i = 0; i < 4; ++i) { backMask[i] = new Mat(); Cv2.InRange( input, new Scalar(bHueL[i], bSatL[i], bvalL[i]), new Scalar(bHueH[i], bSatH[i], bvalH[i]), backMask[i]); } Cv2.BitwiseOr(backMask[0], backMask[0], backMaskfin); Cv2.BitwiseOr(backMaskfin, backMask[1], backMaskfin); Cv2.BitwiseOr(backMaskfin, backMask[2], backMaskfin); Cv2.BitwiseOr(backMaskfin, backMask[3], backMaskfin); Mat stElement = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(8, 8)); Cv2.MorphologyEx(backMaskfin, backMaskfin, MorphTypes.Open, stElement); Cv2.MorphologyEx(backMaskfin, backMaskfin, MorphTypes.Close, stElement); Cv2.Dilate(backMaskfin, backMaskfin, stElement, new Point(-1, -1), 3); return(backMaskfin); }
public static FormExtractionResult ProcessImage(string filename, FormExtractionOptions options = null) { if (options == null) { // Assume recommanded parameters. options = new FormExtractionOptions(); } var orig = new Mat(filename); var image = new Mat(filename, ImreadModes.GrayScale); Cv2.AdaptiveThreshold(image, image, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 9, 4); // Resize image if too large. if (image.Width > options.ResizeWidth) { var height = options.ResizeWidth * image.Height / image.Width; Cv2.Resize(image, image, new Size(options.ResizeWidth, height)); } Cv2.BitwiseNot(image, image); Cv2.Dilate(image, image, Cv2.GetStructuringElement(MorphShapes.Cross, new Size(2, 2))); MatOfByte mat = new MatOfByte(image); MatIndexer <byte> indexer = mat.GetIndexer(); var row = image.Height; var col = image.Width; Mat newImage = new Mat(row, col, MatType.CV_8UC3); newImage.SetTo(Scalar.Black); // We must determine if it "may" be an interesting blob. Stopwatch watch = new Stopwatch(); watch.Start(); int[] imgData = new int[row * col]; for (int y = 0; y < row; y++) { for (int x = 0; x < col; x++) { imgData[y + x * row] = indexer[y, x]; } } var result = HasBoxes(imgData, row, col, options); watch.Stop(); result.Duration = watch.Elapsed; // Preview if (result.Boxes.Any() && image.Width != 0 && options.ShowDebugImage) { var img = CreateImage(result.DebugImg, hasColor: true); Cv2.BitwiseOr(newImage, img, newImage); Cv2.BitwiseNot(image, image); int width = 400; var height = width * image.Height / image.Width; Cv2.Resize(orig, orig, new Size(width, height)); Cv2.Resize(image, image, new Size(width, height)); Cv2.Resize(newImage, newImage, new Size(width, height)); using (new Window("orig", orig)) using (new Window("pre", image)) using (new Window("post", newImage)) { Cv2.WaitKey(); Cv2.DestroyAllWindows(); } } // Dispose. orig.Dispose(); image.Dispose(); newImage.Dispose(); mat.Dispose(); return(result); }
static void Main(string[] args) { Console.WriteLine("Hello World!"); Mat foreground = Cv2.ImRead(@"D:\OneDrive\Pictures\butterflyGreenScreen.jpg"); //Mat background = Cv2.ImRead(@"D:\OneDrive\Pictures\city.jpg"); Mat foregroundHSV = foreground.CvtColor(ColorConversionCodes.BGR2HSV); Mat mask = foregroundHSV.InRange(new Scalar(65, 180, 160), new Scalar(80, 255, 230)); Mat invertMask = new Mat(); Cv2.BitwiseNot(mask, invertMask); Mat finalForeground = new Mat(); foreground.CopyTo(finalForeground, invertMask); //Mat finalBackground = new Mat(); //background.CopyTo(finalBackground, mask); //Mat finalImage = new Mat(); //Cv2.BitwiseOr(finalForeground, finalBackground, finalImage); Cv2.NamedWindow("Display", WindowMode.AutoSize); Cv2.SetMouseCallback("Display", (evnt, x, y, flags, _) => { if (x < 0 || x >= foregroundHSV.Width || y < 0 || y >= foregroundHSV.Height) { return; } Vec3b hsv = foregroundHSV.At <Vec3b>(y, x); Console.WriteLine($"H: {hsv.Item0}, S: {hsv.Item1}, V: {hsv.Item2}"); }); VideoCapture capture = new VideoCapture(0); capture.Set(CaptureProperty.FrameWidth, 640); capture.Set(CaptureProperty.FrameHeight, 360); Mat background = new Mat(); Mat finalBackground = new Mat(); Mat finalImage = new Mat(); while (true) { if (!capture.Read(background)) { continue; } background.CopyTo(finalBackground, mask); Cv2.BitwiseOr(finalForeground, finalBackground, finalImage); Cv2.ImShow("Display", finalBackground); Cv2.WaitKey(1); } //Cv2.ImShow("Display", finalImage); //Cv2.WaitKey(0); }
public void FindContours(string sLeftPictureFile, string sRightPictureFile) { Mat tokuLeft = new Mat(); Mat tokuRight = new Mat(); Mat output = new Mat(); AKAZE akaze = AKAZE.Create(); KeyPoint[] keyPointsLeft; KeyPoint[] keyPointsRight; Mat descriptorLeft = new Mat(); Mat descriptorRight = new Mat(); DescriptorMatcher matcher; //マッチング方法 DMatch[] matches; //特徴量ベクトル同士のマッチング結果を格納する配列 //画像をグレースケールとして読み込み、平滑化する Mat Lsrc = new Mat(sLeftPictureFile, ImreadModes.Color); //画像をグレースケールとして読み込み、平滑化する Mat Rsrc = new Mat(sRightPictureFile, ImreadModes.Color); //特徴量の検出と特徴量ベクトルの計算 akaze.DetectAndCompute(Lsrc, null, out keyPointsLeft, descriptorLeft); akaze.DetectAndCompute(Rsrc, null, out keyPointsRight, descriptorRight); //画像1の特徴点をoutput1に出力 Cv2.DrawKeypoints(Lsrc, keyPointsLeft, tokuLeft); Image imageLeftToku = BitmapConverter.ToBitmap(tokuLeft); pictureBox3.SizeMode = PictureBoxSizeMode.Zoom; pictureBox3.Image = imageLeftToku; tokuLeft.SaveImage("result/LeftToku.jpg"); //画像2の特徴点をoutput1に出力 Cv2.DrawKeypoints(Rsrc, keyPointsRight, tokuRight); Image imageRightToku = BitmapConverter.ToBitmap(tokuRight); pictureBox4.SizeMode = PictureBoxSizeMode.Zoom; pictureBox4.Image = imageRightToku; tokuRight.SaveImage("result/RightToku.jpg"); //総当たりマッチング matcher = DescriptorMatcher.Create("BruteForce"); matches = matcher.Match(descriptorLeft, descriptorRight); Cv2.DrawMatches(Lsrc, keyPointsLeft, Rsrc, keyPointsRight, matches, output); output.SaveImage(@"result\output.jpg"); int size = matches.Count(); var getPtsSrc = new Vec2f[size]; var getPtsTarget = new Vec2f[size]; int count = 0; foreach (var item in matches) { var ptSrc = keyPointsLeft[item.QueryIdx].Pt; var ptTarget = keyPointsRight[item.TrainIdx].Pt; getPtsSrc[count][0] = ptSrc.X; getPtsSrc[count][1] = ptSrc.Y; getPtsTarget[count][0] = ptTarget.X; getPtsTarget[count][1] = ptTarget.Y; count++; } // SrcをTargetにあわせこむ変換行列homを取得する。ロバスト推定法はRANZAC。 var hom = Cv2.FindHomography( InputArray.Create(getPtsSrc), InputArray.Create(getPtsTarget), HomographyMethods.Ransac); // 行列homを用いてSrcに射影変換を適用する。 Mat WarpedSrcMat = new Mat(); Cv2.WarpPerspective( Lsrc, WarpedSrcMat, hom, new OpenCvSharp.Size(Rsrc.Width, Rsrc.Height)); WarpedSrcMat.SaveImage(@"result\Warap.jpg"); //画像1の特徴点をoutput1に出力 Image imageLeftSyaei = BitmapConverter.ToBitmap(WarpedSrcMat); pictureBox5.SizeMode = PictureBoxSizeMode.Zoom; pictureBox5.Image = imageLeftSyaei; //画像2の特徴点をoutput1に出力 Image imageRightSyaei = BitmapConverter.ToBitmap(Rsrc); pictureBox6.SizeMode = PictureBoxSizeMode.Zoom; pictureBox6.Image = imageRightSyaei; Mat LmatFloat = new Mat(); WarpedSrcMat.ConvertTo(LmatFloat, MatType.CV_16SC3); Mat[] LmatPlanes = LmatFloat.Split(); Mat RmatFloat = new Mat(); Rsrc.ConvertTo(RmatFloat, MatType.CV_16SC3); Mat[] RmatPlanes = RmatFloat.Split(); Mat diff0 = new Mat(); Mat diff1 = new Mat(); Mat diff2 = new Mat(); Cv2.Absdiff(LmatPlanes[0], RmatPlanes[0], diff0); Cv2.Absdiff(LmatPlanes[1], RmatPlanes[1], diff1); Cv2.Absdiff(LmatPlanes[2], RmatPlanes[2], diff2); Cv2.MedianBlur(diff0, diff0, 5); Cv2.MedianBlur(diff1, diff1, 5); Cv2.MedianBlur(diff2, diff2, 5); diff0.SaveImage("result/diff0.jpg"); diff1.SaveImage("result/diff1.jpg"); diff2.SaveImage("result/diff2.jpg"); Mat wiseMat = new Mat(); Cv2.BitwiseOr(diff0, diff1, wiseMat); Cv2.BitwiseOr(wiseMat, diff2, wiseMat); wiseMat.SaveImage("result/wiseMat.jpg"); Mat openingMat = new Mat(); Cv2.MorphologyEx(wiseMat, openingMat, MorphTypes.Open, new Mat()); Mat dilationMat = new Mat(); Cv2.Dilate(openingMat, dilationMat, new Mat()); Cv2.Threshold(dilationMat, dilationMat, 100, 255, ThresholdTypes.Binary); dilationMat.SaveImage(@"result\dilationMat.jpg"); Mat LaddMat = new Mat(); Mat RaddMat = new Mat(); Console.WriteLine(dilationMat.GetType()); Console.WriteLine(Rsrc.GetType()); // dilationMatはグレースケールなので合成先のMatと同じ色空間に変換する Mat dilationScaleMat = new Mat(); Mat dilationColorMat = new Mat(); Cv2.ConvertScaleAbs(dilationMat, dilationScaleMat); Cv2.CvtColor(dilationScaleMat, dilationColorMat, ColorConversionCodes.GRAY2RGB); Cv2.AddWeighted(WarpedSrcMat, 0.3, dilationColorMat, 0.7, 0, LaddMat); Cv2.AddWeighted(Rsrc, 0.3, dilationColorMat, 0.7, 0, RaddMat); Image LaddImage = BitmapConverter.ToBitmap(LaddMat); pictureBox7.SizeMode = PictureBoxSizeMode.Zoom; pictureBox7.Image = LaddImage; Image RaddImage = BitmapConverter.ToBitmap(RaddMat); pictureBox8.SizeMode = PictureBoxSizeMode.Zoom; pictureBox8.Image = RaddImage; RaddMat.SaveImage(@"result\Result.jpg"); MessageBox.Show("Done!"); }
public static unsafe void Accumulate(Mat edges, Mat dx, Mat dy, int minRadius, int maxRadius, float idp, List <Mat> accumVec, Mat <byte> nz) { Range boundaries = new Range(0, edges.Rows); int acols = (int)Math.Ceiling(edges.Cols * idp); int arows = (int)Math.Ceiling(edges.Rows * idp); int astep = acols + 2; Mat accumLocal = new Mat(arows + 2, acols + 2, MatType.CV_32SC1, Scalar.All(0)); int * adataLocal = (int *)accumLocal.Ptr(0); Mat <byte> nzLocal = new Mat <byte>(nz.Rows, nz.Cols); int startRow = boundaries.Start; int endRow = boundaries.End; int numCols = edges.Cols; if (edges.IsContinuous() && dx.IsContinuous() && dy.IsContinuous()) { numCols *= (boundaries.End - boundaries.Start); endRow = boundaries.Start + 1; } for (int y = startRow; y < endRow; ++y) { byte * edgeData = (byte *)edges.Ptr(y); short *dxData = (short *)dx.Ptr(y); short *dyData = (short *)dy.Ptr(y); int x = 0; for (; x < numCols; ++x) { for (; x < numCols && edgeData[x] == 0; ++x) { ; } if (x == numCols) { continue; } float vx, vy; int sx, sy, x0, y0, x1, y1; vx = dxData[x]; vy = dyData[x]; if (vx == 0 && vy == 0) { continue; } float mag = (float)Math.Sqrt(vx * vx + vy * vy); if (mag < 1.0f) { continue; } Point pt = new Point(x % edges.Cols, y + x / edges.Cols); nzLocal.Set(pt.Y, pt.X, 1); // sx = (int)Math.Round((vx * idp) * 1024 / mag); sy = (int)Math.Round((vy * idp) * 1024 / mag); x0 = (int)Math.Round((pt.X * idp) * 1024); y0 = (int)Math.Round((pt.Y * idp) * 1024); // Step from min_radius to max_radius in both directions of the gradient for (int k1 = 0; k1 < 2; k1++) { x1 = x0 + minRadius * sx; y1 = y0 + minRadius * sy; for (int r = minRadius; r <= maxRadius; x1 += sx, y1 += sy, r++) { int x2 = x1 >> 10, y2 = y1 >> 10; if ((uint)x2 >= (uint)acols || (uint)y2 >= (uint)arows) { break; } adataLocal[y2 * astep + x2]++; } sx = -sx; sy = -sy; } } } accumVec.Add(accumLocal); Cv2.BitwiseOr(nz, nzLocal, nz); }
public void GetDiffFrame(int width, int height, out double[] buf) { buf = new double[width * height]; var frame = new Mat(); var diff = new Mat(); if (capture.Read(frame)) { frame = frame.Resize(new Size(width, height)); Cv2.CvtColor(frame, frame, ColorConversionCodes.BGR2GRAY); if (PrevFrame != null) { diff = frame.Clone(); Cv2.Absdiff(frame, PrevFrame, diff); Cv2.Threshold(diff, diff, byte.MaxValue * 0.25, byte.MaxValue, ThresholdTypes.Binary); Point[][] contours; HierarchyIndex[] hierarchyIndexes; Cv2.FindContours(diff.Clone(), out contours, out hierarchyIndexes, RetrievalModes.List, ContourApproximationModes.ApproxTC89KCOS); if (contours.Length > 0) { var points = new List <Point>(); for (int idx_cnt = 0; idx_cnt < contours.GetLength(0); ++idx_cnt) { if (hierarchyIndexes[idx_cnt].Parent != -1) { continue; } points.AddRange(contours[idx_cnt]); } Cv2.DrawContours(diff, new List <List <Point> >(new List <Point>[] { new List <Point>(Cv2.ConvexHull(points.ToArray())) }), 0, new Scalar(byte.MaxValue), -1); } var masked = diff.Clone(); frame.CopyTo(masked, diff); Cv2.BitwiseOr(diff, PrevDiffFrame, diff); Cv2.AddWeighted(masked, 0.5, diff, 0.5, 0, diff); if (PrevFrame != null) { unsafe { byte *p = (byte *)frame.Data; byte *pv = (byte *)diff.Data; for (int i = 0; i < width * height; i++) { buf[i] = (double)pv[i] / byte.MaxValue; } } } } if (PrevFrame == null) { PrevFrame = frame.Clone(); PrevDiffFrame = new Mat(PrevFrame.Size(), PrevFrame.Type()); } else { double weight = 0.75; Cv2.AddWeighted(PrevFrame, weight, frame, 1 - weight, 0, PrevFrame); PrevDiffFrame = diff.Clone(); } } }
static void Main(string[] args) { if (!Directory.Exists(Settings.Images.Output)) { Directory.CreateDirectory(Settings.Images.Output); } if (!Directory.Exists(Settings.Images.Dump)) { Directory.CreateDirectory(Settings.Images.Dump); } var listOfImages = Directory.GetFiles(Settings.Images.Source, "*.jpg").ToList(); //!Uncomment next line for select images by freq listOfImages = listOfImages.Where(x => x.Contains("940")).ToList(); //! Comment from this to dump loading for dump load, lol //? get list of all filenames without .jpg and generate cntr PalmsList listOfImages.ForEach(x => { x = x.Remove(0, x.LastIndexOf('\\') + 1).Replace(".jpg", ""); var owner = x.Substring(0, x.Length - 3); PalmsList.Add(new PalmModel() { Id = x.Substring(x.Length - 2), Owner = owner, FileName = x, Directory = $@"{Settings.Images.Output}{owner}" }); }); //? get names and create name collection //? create dirs for saving data var userNames = PalmsList.DistinctBy(x => x.Owner); userNames.ForEach(x => { UsersList.Add(new UserModel() { Name = x.Owner, Patterns = new List <Mat> (), Directory = x.Directory }); if (Directory.Exists(x.Directory) && Directory.GetFiles(x.Directory).Length > 0) { Directory.Delete(x.Directory, true); // recursive } Directory.CreateDirectory(x.Directory); }); Console.WriteLine($"Total users: {UsersList.Count}"); Console.WriteLine($"Total palm collection: {PalmsList.Count}"); var totalROIExtractionTime = new Stopwatch(); totalROIExtractionTime.Start(); //! ROI extraction Console.WriteLine($"[{DateTime.Now}] ROI extraction"); var ROITask = Task.Factory.StartNew(() => { PalmsList.ForEach(x => { Task.Factory.StartNew(() => { var path = $@"{Settings.Images.Source}\{x.FileName}.jpg"; x.SourceImage = Cv2.ImRead(path, ImreadModes.Color); x.Height = x.SourceImage.Size().Height; x.Width = x.SourceImage.Size().Width; //! apply threshold Cv2.CvtColor(x.SourceImage, x.SourceImage, ColorConversionCodes.BGR2GRAY); // 0, 255 x.ThresholdImage = x.SourceImage.Threshold(5, 255, ThresholdTypes.Otsu); // save for debug #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\binary_{x.Id}.jpg", x.ThresholdImage); #endif //! ROI extraction var i1 = x.Height - 50; var i2 = x.Width - 50; var radius = 50; int pX = 0; int pY = 0; for (int i = 50; i != i1; i++) { for (int j = 50; j != i2; j++) { if (x.ThresholdImage.Get <byte> (i, j) == Settings.COLOR_WHITE) { int a = 0; for (a = 1; a < 360; a++) { var y1 = Convert.ToInt16(j + radius * Math.Cos(a * Math.PI / 180)); var x1 = Convert.ToInt16(i - radius * Math.Sin(a * Math.PI / 180)); if (x1 < 1 || x1 > i1 || y1 < 1 || y1 > i2 || x.ThresholdImage.Get <byte> (x1, y1) == Settings.COLOR_BLACK) { break; } } if (a == 360) { radius += 10; pX = i; pY = j; } } } } radius -= 10; var x0 = Convert.ToInt16(pY - Math.Sqrt(2) * radius / 2); var y0 = Convert.ToInt16(pX - Math.Sqrt(2) * radius / 2); var wsize = Convert.ToInt16(Math.Sqrt(2) * radius); var rect = new Rect(x0, y0, wsize, wsize); // for visual debug Mat drawROIImage = new Mat(); x.SourceImage.CopyTo(drawROIImage); drawROIImage.Rectangle(rect, Scalar.White); x.ROI = new Mat(x.SourceImage, rect) .Resize(new Size(216, 216)); Cv2.Rotate(x.ROI, x.ROI, RotateFlags.Rotate90Counterclockwise); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\ROIOnSource_{x.Id}.jpg", drawROIImage); Cv2.ImWrite($@"{x.Directory}\ROI_{x.Id}.jpg", x.ROI); #endif }, TaskCreationOptions.AttachedToParent | TaskCreationOptions.RunContinuationsAsynchronously); }); }); ROITask.Wait(); totalROIExtractionTime.Stop(); Console.WriteLine($"[{DateTime.Now}] Total ROI extracton time: {totalROIExtractionTime.Elapsed}"); //! Create dump Dump.ROI.Create(Settings.Images.Dump, PalmsList); //! Uncomment next block for loading images from dump and comment all lines before this // PalmsList = Dump.ROI.Load(Settings.Images.Dump, listOfImages); // var countFrom = 0; // var countTo = PalmsList.Count; // ------------------------------ //! Apply filters Console.WriteLine($"[{DateTime.Now}] Apply filters to ROI image"); totalROIExtractionTime.Reset(); totalROIExtractionTime.Start(); var filtersTask = Task.Factory.StartNew(() => { PalmsList.ForEach(x => { Task.Factory.StartNew(() => { //! Reduce noise Cv2.MedianBlur(x.ROI, x.ROI, 5); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\ROI_Median_{x.Id}.jpg", x.ROI); #endif // Cv2.CvtColor(x.ROI, x.ROI, ColorConversionCodes.BGR2GRAY); Cv2.FastNlMeansDenoising(x.ROI, x.ROI); Cv2.CvtColor(x.ROI, x.ROI, ColorConversionCodes.GRAY2BGR); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\reduce_noise_{x.Id}.jpg", x.ROI); #endif //! Equalize hist var element = Cv2.GetStructuringElement(MorphShapes.Cross, Settings.ElementSize); // new Mat(7, 7, MatType.CV_8U); Cv2.MorphologyEx(x.ROI, x.ROI, MorphTypes.Open, element); Cv2.CvtColor(x.ROI, x.ROI, ColorConversionCodes.BGR2YUV); // Cv2.EqualizeHist(x.ROI, x.ROI); var RGB = Cv2.Split(x.ROI); RGB[0] = RGB[0].EqualizeHist(); RGB[1] = RGB[1].EqualizeHist(); RGB[2] = RGB[2].EqualizeHist(); Cv2.Merge(RGB, x.ROI); Cv2.CvtColor(x.ROI, x.ROI, ColorConversionCodes.YUV2BGR); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\equalized_hist_{x.Id}.jpg", x.ROI); #endif //! Invert image Cv2.BitwiseNot(x.ROI, x.ROI); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\inverted_{x.Id}.jpg", x.ROI); #endif //! Erode image Cv2.CvtColor(x.ROI, x.ROI, ColorConversionCodes.BGR2GRAY); Cv2.Erode(x.ROI, x.ROI, element); #if SAVEALLRESULTS Cv2.ImWrite($@"{x.Directory}\eroded_{x.Id}.jpg", x.ROI); #endif //! Skeletonize var skel = new Mat(x.ROI.Size(), MatType.CV_8UC1, new Scalar(0)); var temp = new Mat(); var eroded = new Mat(); do { Cv2.MorphologyEx(x.ROI, eroded, MorphTypes.Erode, element); Cv2.MorphologyEx(eroded, temp, MorphTypes.Dilate, element); Cv2.Subtract(x.ROI, temp, temp); Cv2.BitwiseOr(skel, temp, skel); eroded.CopyTo(x.ROI); } while (Cv2.CountNonZero(x.ROI) != 0); //! Threshold skeletonized image var thr = skel.Threshold(0, 255, ThresholdTypes.Binary); //! Remove contours thr.Line(new Point(0, 0), new Point(0, thr.Height), Scalar.Black, 2); // rm left contour thr.Line(new Point(0, 0), new Point(thr.Width, 0), Scalar.Black, 2); // rm top contour thr.Line(new Point(thr.Width, thr.Height), new Point(thr.Width, 0), Scalar.Black, 2); // rm right contour thr.Line(new Point(thr.Width, thr.Height), new Point(0, thr.Height), Scalar.Black, 2); // rm bot contour //! Normalize contours element = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(6, 6)); Cv2.Dilate(thr, thr, element); Cv2.Erode(thr, thr, element); Cv2.MorphologyEx(thr, thr, MorphTypes.Gradient, element); Cv2.ImWrite($@"{x.Directory}\{x.Id}.jpg", thr); var owner = UsersList.Find(u => u.Name == x.Owner); owner.Patterns.Add(thr); // add thresholded image to user patterns }, TaskCreationOptions.AttachedToParent | TaskCreationOptions.RunContinuationsAsynchronously); }); }); filtersTask.Wait(); totalROIExtractionTime.Stop(); Console.WriteLine($"[{DateTime.Now}] Total apply filters time: {totalROIExtractionTime.Elapsed}"); //! Create dump with users and they patterns Dump.Patterns.Create(Settings.Images.Dump, UsersList); //! Create CSV file Dump.CSV.Create(Settings.Images.CSV, PalmsList); }
public void proessHand(UnityEngine.Texture texture, ref Texture2D output) { Mat processingImage = OpenCvSharp.Unity.TextureToMat(texture as WebCamTexture); Mat frameCopy = processingImage.Clone(); Cv2.CvtColor(processingImage, processingImage, ColorConversionCodes.BGR2HSV); Mat maskedImage = new Mat(); Mat maskedSkin = new Mat(); Mat maskedBackground = new Mat(); if (Input.GetKey(KeyCode.M)) { useML = !useML; } if (Input.GetKey(KeyCode.R)) { realTimeLearning = !realTimeLearning; } if (Input.GetKey(KeyCode.N)) { deNoise = !deNoise; } if (deNoise) { Cv2.FastNlMeansDenoising(processingImage, processingImage, 1, 2, 5); } if (!useML) { drawColorSampler(processingImage); if (Input.GetKey(KeyCode.B)) { calibrateBackground(frameCopy); } if (Input.GetKey(KeyCode.S)) { calibrateSkin(frameCopy); } background = getBackgroundMask(frameCopy); skin = getSkinMask(frameCopy); Cv2.BitwiseNot(background, background); Cv2.BitwiseOr(skin, background, foreground); Mat debug = getHandContour(skin, frameCopy); Cv2.BitwiseAnd(processingImage, processingImage, maskedSkin, skin); Cv2.BitwiseAnd(processingImage, processingImage, maskedBackground, background); Cv2.BitwiseAnd(frameCopy, frameCopy, maskedImage, foreground); Cv2.CvtColor(maskedImage, maskedImage, ColorConversionCodes.HSV2BGR); Cv2.CvtColor(maskedSkin, maskedSkin, ColorConversionCodes.HSV2BGR); Cv2.CvtColor(maskedBackground, maskedBackground, ColorConversionCodes.HSV2BGR); // Cv2.CvtColor(debug, debug, ColorConversionCodes.HSV2BGR); if (Input.GetKey(KeyCode.Q)) { output = OpenCvSharp.Unity.MatToTexture(maskedSkin, output); } else if (Input.GetKey(KeyCode.W)) { output = OpenCvSharp.Unity.MatToTexture(maskedBackground, output); } else { output = OpenCvSharp.Unity.MatToTexture(debug, output); } } else { background = getBackgroundMask(processingImage); if (realTimeLearning) { bsub.Apply(processingImage, background); } else { bsub.Apply(processingImage, background, 0); } Mat debug = null; Mat kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(8, 8)); Cv2.MorphologyEx(background, background, MorphTypes.Open, kernel); Cv2.MorphologyEx(background, background, MorphTypes.Open, kernel); Cv2.MorphologyEx(background, background, MorphTypes.Close, kernel); //Cv2.Dilate(background, background, kernel, new Point(-1, -1), 1); Cv2.BitwiseAnd(processingImage, processingImage, maskedBackground, background); debug = getHandContour(background, processingImage); // Cv2.CvtColor(maskedBackground, maskedBackground, ColorConversionCodes.HSV2BGR); //Cv2.CvtColor(processingImage, processingImage, ColorConversionCodes.HSV2BGR); Cv2.CvtColor(debug, debug, ColorConversionCodes.HSV2BGR); Cv2.CvtColor(background, background, ColorConversionCodes.GRAY2BGR); if (Input.GetKey(KeyCode.E)) { output = OpenCvSharp.Unity.MatToTexture(background, output); } else { output = OpenCvSharp.Unity.MatToTexture(debug, output); } } }
static void Main(string[] args) { // Used to check memory leak //for (int i = 0; i < 1000; i++) using (var state = new ThreadLocal <FormExtractionHandle>(NativeFormExtraction.CreateFormExtraction)) { GC.Collect(); List <string> pathFiles = GetSamplesAndCleanUpResults(); // For testing: pathFiles = pathFiles.Where(m => m.Contains("form9")).ToList(); int numThread = 1; // Environment.ProcessorCount; var showDebugImage = true; // If true, you may want to use: numThread = 1. Parallel.ForEach(pathFiles, new ParallelOptions { MaxDegreeOfParallelism = numThread }, pathFile => { FormExtractionHandle handle = state.Value; NativeFormExtraction.SetOptions(handle, 800, 25, 15, 5, 20000, 50000, showDebugImage); var resizeWidth = 800; var orig = new Mat(pathFile); var image = new Mat(pathFile, ImreadModes.GrayScale); Cv2.AdaptiveThreshold(image, image, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 9, 4); // Resize image if too large. if (image.Width > resizeWidth) { var height = resizeWidth * image.Height / image.Width; Cv2.Resize(image, image, new Size(resizeWidth, height)); } Cv2.BitwiseNot(image, image); Cv2.Dilate(image, image, Cv2.GetStructuringElement(MorphShapes.Cross, new Size(2, 2))); MatOfByte mat = new MatOfByte(image); MatIndexer <byte> indexer = mat.GetIndexer(); var row = image.Height; var col = image.Width; Mat newImage = new Mat(row, col, MatType.CV_8UC3); newImage.SetTo(Scalar.Black); // We must determine if it "may" be an interesting blob. Stopwatch watch = new Stopwatch(); watch.Start(); int[] imgData = new int[row * col]; for (int y = 0; y < row; y++) { for (int x = 0; x < col; x++) { imgData[y + x * row] = indexer[y, x]; } } var result = NativeFormExtraction.RunFormExtraction(handle, imgData, row, col); if (result != 0) { throw new Exception("Unknown error occured with the function: RunFormExtraction"); } watch.Stop(); Console.WriteLine("Duration: " + watch.Elapsed); if (showDebugImage) { var debugImg = NativeFormExtraction.GetDebugImage(handle, row * col); var img = CreateImage(debugImg, row, col, hasColor: true); Cv2.BitwiseOr(newImage, img, newImage); Cv2.BitwiseNot(image, image); int width = 400; var height = width * image.Height / image.Width; Cv2.Resize(orig, orig, new Size(width, height)); Cv2.Resize(image, image, new Size(width, height)); Cv2.Resize(newImage, newImage, new Size(width, height)); using (new Window("orig", orig)) using (new Window("pre", image)) using (new Window("post", newImage)) { Cv2.WaitKey(); Cv2.DestroyAllWindows(); } } // Dispose. orig.Dispose(); image.Dispose(); newImage.Dispose(); mat.Dispose(); }); } Console.WriteLine("End"); Console.ReadLine(); }
static void Main(string[] args) { //! Create directories for output images if (!Directory.Exists(Settings.Images.Output)) { Directory.CreateDirectory(Settings.Images.Output); } //! create list of images var listOfImages = Directory.GetFiles(Settings.Images.Source, "*.jpg") .Where(x => x.Contains("940")) .Where(x => x.Contains("_l_")) // .Take (6) // take one palm to test .ToList(); //! variables for ROI double radius, a, xx, yy, predictX, predictY, angle; Point centerOfPalm; Point2f centerOfImage; Rect rect; //! variables for extracting file parameters PalmModel[] Palms = new PalmModel[listOfImages.Count]; //! matherials Mat sourceHandle, thresholdHandle, roiHandle, skel, rotatedSource, eroded, thr, matrix = new Mat(); Mat element = Cv2.GetStructuringElement(MorphShapes.Cross, Settings.ElementSize); Mat[] RGB; for (int i = 0; i != listOfImages.Count; i++) { Palms[i] = new PalmModel(); Palms[i].Filename = listOfImages[i].Remove(0, listOfImages[i].LastIndexOf('/') + 1).Replace(".jpg", ""); Palms[i].Owner = Palms[i].Filename.Substring(0, Palms[i].Filename.IndexOf('_')); Palms[i].Id = Palms[i].Filename.Substring(Palms[i].Filename.LastIndexOf('_') + 2); Palms[i].Type = (Palms[i].Filename.IndexOf('r') == -1 ? 'l' : 'r'); Palms[i].Directory = $"{Settings.Images.Output}{Palms[i].Type}/{Palms[i].Owner}"; Palms[i].Path = $"{Settings.Images.Source}/{Palms[i].Filename}.jpg"; if (Directory.Exists(Palms[i].Directory) && Directory.GetFiles(Palms[i].Directory).Length > 0) { Directory.Delete(Palms[i].Directory, true); // recursive } Directory.CreateDirectory(Palms[i].Directory); } Console.WriteLine($"[{DateTime.Now}] Transform started"); var workerTime = new Stopwatch(); workerTime.Start(); for (int i = 0; i != listOfImages.Count; i++) { if (i % 10 == 0) { Console.WriteLine($"{i}.{listOfImages.Count}"); } // Read sample image sourceHandle = Cv2.ImRead(Palms[i].Path, ImreadModes.AnyColor); // Get center of image centerOfImage = new Point2f(sourceHandle.Width / 2, sourceHandle.Height / 2); // Start loop by rotations for (int j = 0; j != 180; j++) { // change rotation angle angle = j * 2; rotatedSource = new Mat(); // get and apply image rotation matrix by angle matrix = Cv2.GetRotationMatrix2D(centerOfImage, angle, 1.0); Cv2.WarpAffine(sourceHandle, rotatedSource, matrix, new Size(sourceHandle.Width, sourceHandle.Height)); // apply threshold thresholdHandle = rotatedSource.Threshold(0, 255, ThresholdTypes.Otsu); /*// apply transform distance and convert to cv_8u * thresholdHandle.DistanceTransform (DistanceTypes.L2, DistanceMaskSize.Precise); * thresholdHandle.ConvertTo (thresholdHandle, MatType.CV_8U); * * // get center of palm * centerOfPalm = GetHandCenter (thresholdHandle, out radius);*/ double radius1; Cv2.DistanceTransform(thresholdHandle, matrix, DistanceTypes.L2, DistanceMaskSize.Mask5); matrix.ImWrite($"{Palms[i].Directory}/002_distance-transform.jpg"); int[] maxIdx = new int[2]; int[] minIdx = new int[2]; Cv2.MinMaxIdx(matrix, out radius1, out radius, minIdx, maxIdx, thresholdHandle); centerOfPalm = new OpenCvSharp.Point(maxIdx[1], maxIdx[0]); // calculate ROI a = (2 * radius) / Math.Sqrt(2); xx = centerOfPalm.X - radius * Math.Cos(45 * Math.PI / 180); yy = centerOfPalm.Y - radius * Math.Sin(45 * Math.PI / 180); if (xx < 0) { a += xx; // 200 + -2 -> 200 - 2 = 198 xx = 0; } if (yy < 0) { a += yy; // 120 + -10 -> 120 - 10 = 110 yy = 0; } predictX = xx + a; predictY = yy + a; if (predictX > rotatedSource.Width) // if more { xx -= predictX - rotatedSource.Width; // (590 - 580) = 10 } if (predictY > rotatedSource.Height) { yy -= predictY - rotatedSource.Height; // 800 - 640 = 160 } /* * rect = new Rect(new Point(xx + 20, yy + 20), new Size(a, a)); * rect = new Rect(new Point(xx - 20, yy - 20), new Size(a, a)); * rect = new Rect(new Point(xx - 20, yy + 20), new Size(a, a)); * rect = new Rect(new Point(xx + 20, yy - 20), new Size(a, a)); */ rect = new Rect(new Point(xx, yy), new Size(a, a)); roiHandle = new Mat(rotatedSource, rect) .Resize(Const.ResizeValue); //! apply filters Cv2.MedianBlur(roiHandle, roiHandle, 5); // Cv2.CvtColor(roiHandle, roiHandle, ColorConversionCodes.BGR2GRAY); Cv2.FastNlMeansDenoising(roiHandle, roiHandle); Cv2.CvtColor(roiHandle, roiHandle, ColorConversionCodes.GRAY2BGR); //! Equalize hist Cv2.MorphologyEx(roiHandle, roiHandle, MorphTypes.Open, element); Cv2.CvtColor(roiHandle, roiHandle, ColorConversionCodes.BGR2YUV); RGB = Cv2.Split(roiHandle); RGB[0] = RGB[0].EqualizeHist(); RGB[1] = RGB[1].EqualizeHist(); RGB[2] = RGB[2].EqualizeHist(); Cv2.Merge(RGB, roiHandle); Cv2.CvtColor(roiHandle, roiHandle, ColorConversionCodes.YUV2BGR); //! Invert image Cv2.BitwiseNot(roiHandle, roiHandle); //! Erode image Cv2.CvtColor(roiHandle, roiHandle, ColorConversionCodes.BGR2GRAY); Cv2.Erode(roiHandle, roiHandle, element); //! Skeletonize skel = new Mat(roiHandle.Size(), MatType.CV_8UC1, Const.ZeroScalar); rotatedSource = new Mat(); eroded = new Mat(); thr = new Mat(); do { Cv2.MorphologyEx(roiHandle, eroded, MorphTypes.Erode, element); Cv2.MorphologyEx(eroded, rotatedSource, MorphTypes.Dilate, element); Cv2.Subtract(roiHandle, rotatedSource, rotatedSource); Cv2.BitwiseOr(skel, rotatedSource, skel); eroded.CopyTo(roiHandle); } while (Cv2.CountNonZero(roiHandle) != 0); //! Threshold skeletonized image thr = skel.Threshold(0, 255, ThresholdTypes.Binary); //! Remove contours thr.Line(Const.Zero, new Point(0, thr.Height), Scalar.Black, 2); // rm left contour thr.Line(Const.Zero, new Point(thr.Width, 0), Scalar.Black, 2); // rm top contour thr.Line(new Point(thr.Width, thr.Height), new Point(thr.Width, 0), Scalar.Black, 2); // rm right contour thr.Line(new Point(thr.Width, thr.Height), new Point(0, thr.Height), Scalar.Black, 2); // rm bot contour //! Partion lines if (Const.MODE_TYPE) { Cv2.GaussianBlur(thr, thr, new Size(7, 7), sigmaX: 5); Cv2.MorphologyEx(thr, thr, MorphTypes.Gradient, element); Cv2.BitwiseNot(thr, thr); } thr.ImWrite($"{Palms[i].Directory}/{Palms[i].Id}-{angle}.jpg"); } } workerTime.Stop(); Console.WriteLine($"[{DateTime.Now}] Elapsed time: {workerTime.Elapsed}"); }