123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796 |
- using OpenCvSharp;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading.Tasks;
- namespace SmartCoalApplication.Base.CommTool
- {
- public class BinaryTools
- {
- public static Dictionary<int, int> keyValuePairs = new Dictionary<int, int>();
- public static Mat rgb_ap, temp_ap, original;
- public static Vec4b vec4B;
- /// <summary>
- /// 新碎屑删除,使用连通分量找寻碎屑
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public unsafe static Mat DebrisRemoval_New(Mat src, int v = 20)
- {
- try
- {
- Mat[] arr = src.Split();
- rgb_ap = Tools.MergeMatFromMatArr(arr);
- if(arr.Length>3)
- temp_ap = arr[3].Clone();
- //寻找连通分量
- Mat labelMat = new Mat();
- Mat stats = new Mat();
- Mat centroids = new Mat();
- int nonenum = Cv2.ConnectedComponentsWithStats(src.CvtColor(ColorConversionCodes.BGRA2GRAY), labelMat, stats, centroids, PixelConnectivity.Connectivity8);
- //寻找在范围内需要删除的碎屑
- keyValuePairs.Clear();
- for (int h = 1; h < centroids.Height; h++)
- {
- int areaField1 = stats.At<int>(h, 4);
- if (0 <= areaField1 && areaField1 <= v)
- {
- keyValuePairs.Add(h, 1);
- }
- }
- labelMat.ForEachAsInt32(CommonForEachForInt32);
- //合并rgb和透明度
- Mat[] mats = rgb_ap.Split();
- arr[0] = mats[0];
- arr[1] = mats[1];
- arr[2] = mats[2];
- if (arr.Length > 3)
- arr[3] = temp_ap;
- Cv2.Merge(arr, src);
- }
- catch (Exception)
- {
- }
- finally
- {
- keyValuePairs.Clear();
- if (rgb_ap != null && !rgb_ap.IsDisposed)
- {
- rgb_ap.Dispose();
- rgb_ap = null;
- }
- if (temp_ap != null && !temp_ap.IsDisposed)
- {
- temp_ap.Dispose();
- temp_ap = null;
- }
- System.GC.Collect();
- }
- return src;
- }
- public unsafe static Mat DebrisRemoval_New_1(Mat src, int v = 20)
- {
- try
- {
- temp_ap = src.Clone();
- //寻找连通分量
- Mat labelMat = new Mat();
- Mat stats = new Mat();
- Mat centroids = new Mat();
- int nonenum = Cv2.ConnectedComponentsWithStats(src, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
- //寻找在范围内需要删除的碎屑
- keyValuePairs.Clear();
- for (int h = 1; h < centroids.Height; h++)
- {
- int areaField1 = stats.At<int>(h, 4);
- if (0 <= areaField1 && areaField1 <= v)
- {
- keyValuePairs.Add(h, 1);
- }
- }
- labelMat.ForEachAsInt32(CommonForEachForInt32_1);
- temp_ap.CopyTo(src);
- }
- catch (Exception)
- {
- }
- finally
- {
- keyValuePairs.Clear();
- if (rgb_ap != null && !rgb_ap.IsDisposed)
- {
- rgb_ap.Dispose();
- rgb_ap = null;
- }
- if (temp_ap != null && !temp_ap.IsDisposed)
- {
- temp_ap.Dispose();
- temp_ap = null;
- }
- System.GC.Collect();
- }
- return src;
- }
- private unsafe static void CommonForEachForInt32(int* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- int v = *value;
- if (v > 0 && keyValuePairs.ContainsKey(v))
- {
- rgb_ap.Set<Vec3b>(y, x, new Vec3b(0, 0, 0));
- if(temp_ap!=null)
- temp_ap.Set<int>(y, x, 0);
- }
- }
- private unsafe static void CommonForEachForInt32_1(int* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- int v = *value;
- if (v > 0 && keyValuePairs.ContainsKey(v))
- {
- if (temp_ap != null)
- temp_ap.Set<int>(y, x, 0);
- }
- }
- public unsafe static Mat HoleFilling_NewWithView(Mat src, Vec4b vec4b)
- {
- vec4B = vec4b;
- Mat[] arr2 = src.Split();
- Mat tempc = arr2[3];
- //去掉透明层
- Mat mat = src.CvtColor(ColorConversionCodes.BGRA2BGR);
- //填充孔洞
- mat = Tools.FillHole(mat, new Scalar(255 - vec4B.Item0, 255 - vec4B.Item1, 255 - vec4B.Item2));
- tempc = Tools.FillHole(tempc, new Scalar(255));
- //循环处理
- mat.ForEachAsVec3b(RGBForEachAsByteForHoleFillingNewWithView);
- Mat[] arr1 = mat.Split();
- arr2[0] = arr1[0];
- arr2[1] = arr1[1];
- arr2[2] = arr1[2];
- arr2[3] = tempc;
- Cv2.Merge(arr2, src);
- if (mat != null && !mat.IsDisposed) mat.Dispose();
- if (tempc != null && !tempc.IsDisposed) tempc.Dispose();
- System.GC.Collect();
- return src;
- }
- private unsafe static void RGBForEachAsByteForHoleFillingNewWithView(Vec3b* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- if (value->Item0 == 255 && value->Item1 == 255 && value->Item2 == 255)
- {
- value->Item0 = vec4B.Item0;
- value->Item1 = vec4B.Item1;
- value->Item2 = vec4B.Item2;
- }
- else
- {
- value->Item0 = 255;
- value->Item1 = 255;
- value->Item2 = 255;
- }
- }
- public static double CalcNodularity(OpenCvSharp.Point[] contours)
- {
- Point2f point;
- float radius;
- double area = Cv2.ContourArea(contours);
- if (contours.Length > 500)
- {
- Cv2.MinEnclosingCircle(Cv2.ConvexHull(contours, true), out point, out radius);
- }
- else
- {
- Cv2.MinEnclosingCircle(contours, out point, out radius);
- }
- return area / (Math.PI * radius * radius);
- }
- public static bool WithinContour(List<OpenCvSharp.Point[]> contoursAll, OpenCvSharp.Point[] now)
- {
- foreach (OpenCvSharp.Point[] ps in contoursAll)
- {
- double inside = Cv2.PointPolygonTest(now, ps[0], true);
- if (inside > 0)
- return true;
- }
- return false;
- }
- /// <summary>
- /// 估算适合的阈值
- /// </summary>
- /// <param name="edge"></param>
- /// <param name="first"></param>
- /// <returns></returns>
- public static float CalcSuitableValue(Mat edge, bool first = true)
- {
- //寻找较适合的阈值
- float[] hist_float = HistTools.CalcHist(edge);
- //直方图平滑
- int[] hist_int = HistTools.Smooth(hist_float, 5);//10
- //寻找所有的峰
- List<int> mountainsList = new List<int>();
- List<int[]> mountainsArrList = new List<int[]>();
- List<int[]> mountainsArrListBackUp = new List<int[]>();
- Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List<string>(), 15);
- mountainsList.Sort();
- if (first)
- return (mountainsList.Min() - 10) <= 0 ? 70 : (mountainsList.Min() - 10);
- else
- return mountainsList[mountainsList.IndexOf(mountainsList.Min()) + 1];
- }
- public static float CalcSuitableValueForUnderCut(Mat edge, bool first = true)
- {
- //寻找较适合的阈值
- float[] hist_float = HistTools.CalcHist(edge);
- //直方图平滑
- int[] hist_int = HistTools.Smooth(hist_float, 10);
- //寻找所有的峰
- List<int> mountainsList = new List<int>();
- List<int[]> mountainsArrList = new List<int[]>();
- List<int[]> mountainsArrListBackUp = new List<int[]>();
- Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List<string>(), 15);
- mountainsList.Sort();
- if (first)
- return (mountainsList.Min() - 10) <= 0 ? 70 : (mountainsList.Min());
- else
- return mountainsList[mountainsList.IndexOf(mountainsList.Min()) + 1];
- }
- /// <summary>
- /// 最找最大的峰的右侧的谷
- /// </summary>
- /// <param name="edge"></param>
- /// <returns></returns>
- public static float CalcSuitableValueForMax(Mat edge)
- {
- //寻找较适合的阈值
- float[] hist_float = HistTools.CalcHist(edge);
- //直方图平滑
- int[] hist_int = HistTools.Smooth(hist_float, 20);
- for (int i = 0; i < hist_int.Length; i++)
- if (hist_int[i] < 3000) hist_int[i] = 0;
- //寻找所有的峰
- List<int> mountainsList = new List<int>();
- List<int[]> mountainsArrList = new List<int[]>();
- List<int[]> mountainsArrListBackUp = new List<int[]>();
- Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List<string>(), 15);
- int returnV = 0;
- int temp = 0;
- int l = 0;
- for(int i=0; i< mountainsList.Count; i++)
- {
- if(mountainsList[i]<200 && temp < mountainsList[i])
- {
- temp = mountainsList[i];
- returnV = mountainsArrList[i][1];
- l = i;
- }
- }
- if(returnV > 200) return mountainsArrList[l-1][1];
- return returnV;
- }
- /// <summary>
- /// 新版本删除边界
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public static Mat DeleteContours_New(Mat src)
- {
- Rect rect;
- Mat[] arr = src.Split();
- Mat rgb = Tools.MergeMatFromMatArr(arr);
- Mat temp_1 = arr[3].Clone();
- for (int h = 0; h < temp_1.Width; h++)
- {
- byte vec4B_top = temp_1.At<byte>(0, h);
- if (vec4B_top > 0)
- {
- Cv2.FloodFill(rgb, new OpenCvSharp.Point(h, 0), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- Cv2.FloodFill(temp_1, new OpenCvSharp.Point(h, 0), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- }
- }
- for (int h = 0; h < temp_1.Width; h++)
- {
- byte vec4B_bottom = temp_1.At<byte>(temp_1.Height - 1, h);
- if (vec4B_bottom > 0)
- {
- Cv2.FloodFill(rgb, new OpenCvSharp.Point(h, temp_1.Height - 1), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- Cv2.FloodFill(temp_1, new OpenCvSharp.Point(h, temp_1.Height - 1), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- }
- }
- for (int y = 0; y < temp_1.Height; y++)
- {
- Vec4b vec4B_top = temp_1.At<Vec4b>(y, 0);
- if (vec4B_top.Item3 > 0)
- {
- Cv2.FloodFill(rgb, new OpenCvSharp.Point(0, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- Cv2.FloodFill(temp_1, new OpenCvSharp.Point(0, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- }
- }
- for (int y = 0; y < temp_1.Height; y++)
- {
- byte vec4B_top = temp_1.At<byte>(y, temp_1.Width - 1);
- if (vec4B_top > 0)
- {
- Cv2.FloodFill(rgb, new OpenCvSharp.Point(temp_1.Width - 1, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- Cv2.FloodFill(temp_1, new OpenCvSharp.Point(temp_1.Width - 1, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
- }
- }
- Mat[] mats = rgb.Split();
- arr[0] = mats[0];
- arr[1] = mats[1];
- arr[2] = mats[2];
- arr[3] = temp_1;
- Cv2.Merge(arr, src);
- return src;
- }
- static Mat phaseTemp1;
- static double contrast = 2;
- static int brightness = 0;
- /// <summary>
- /// 亮度/对比度/伽马值
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public unsafe static Mat BCGTransferFunction(Mat src)
- {
- if (phaseTemp1 != null) phaseTemp1 = null;
- contrast = 1.7;
- phaseTemp1 = new Mat(src.Size(), MatType.CV_8UC3, Scalar.All(0)); //创建一个和原图像大小相同,类型相同,像素值为0的图像。
- Mat imageGamma = null;
- try
- {
- double gamma = 1;
- src = src.CvtColor(ColorConversionCodes.GRAY2BGR);
- contrast = (contrast - 1.0) / 2.0 + 1.0;//待确认参数范围
- src.ForEachAsVec3b(ForeachFunctionByteForBCGTransferMultiChannel);
- imageGamma = new Mat();
- //灰度归一化
- phaseTemp1.ConvertTo(imageGamma, MatType.CV_64F, 1.0 / 255, 0);
- Cv2.Pow(imageGamma, gamma, imageGamma);
- imageGamma.ConvertTo(imageGamma, MatType.CV_8U, 255, 0);
- imageGamma.CopyTo(phaseTemp1);
- phaseTemp1.CopyTo(src);
- return src.CvtColor(ColorConversionCodes.BGR2GRAY);
- }
- catch (Exception ex)
- {
- throw ex;
- }
- finally
- {
- if (imageGamma != null && !imageGamma.IsDisposed)
- {
- imageGamma.Dispose();
- }
- if (phaseTemp1 != null && !phaseTemp1.IsDisposed)
- {
- phaseTemp1.Dispose();
- phaseTemp1 = null;
- }
- GC.Collect();
- }
- }
- private unsafe static void ForeachFunctionByteForBCGTransferMultiChannel(Vec3b* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- double v0 = contrast * (value->Item0 - 128.0) + 128.0 + brightness;
- double v1 = contrast * (value->Item1 - 128.0) + 128.0 + brightness;
- double v2 = contrast * (value->Item2 - 128.0) + 128.0 + brightness;
- if (v0 > 255) v0 = 255;
- else if (v0 < 0) v0 = 0;
- if (v1 > 255) v1 = 255;
- else if (v1 < 0) v1 = 0;
- if (v2 > 255) v2 = 255;
- else if (v2 < 0) v2 = 0;
- Vec3b vec = new Vec3b();
- vec[0] = (byte)v0;
- vec[1] = (byte)v1;
- vec[2] = (byte)v2;
- phaseTemp1.Set<Vec3b>(y, x, vec);
- }
- private unsafe static void ForeachFunctionByteForBCGTransferOneChannel(double* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- double v = contrast * (*value - 128.0) + 128.0 + 0;
- if (v > 255) v = 255;
- else if (v < 0) v = 0;
- phaseTemp1.Set<double>(y, x, v);
- }
- /// <summary>
- /// unsharp mask
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public static Mat BlurMaskFunction(Mat src, float radius= 4f * 3.14f, int threshold = 1, float amount = 300f)
- {
- Bitmap map = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(src);
- //像素矩阵
- var inPixels = ByteArray(map);
- var workPixels = new int[inPixels.Length];
- var outPixels = new int[inPixels.Length];
- //半径
- if (radius > 0)
- {
- Kernel kernel = CreateKernel(radius);
- ConvolveAndTranspose(kernel, inPixels, workPixels, map.Width, map.Height, true, true, false, 1);
- ConvolveAndTranspose(kernel, workPixels, outPixels, map.Height, map.Width, true, false, true, 1);
- }
- for (int index = 0; index < inPixels.Length; index++)
- {
- int rgb1 = inPixels[index];
- int r1 = (rgb1 >> 16) & 0xff;
- int g1 = (rgb1 >> 8) & 0xff;
- int b1 = rgb1 & 0xff;
- int rgb2 = outPixels[index];
- int r2 = (rgb2 >> 16) & 0xff;
- int g2 = (rgb2 >> 8) & 0xff;
- int b2 = rgb2 & 0xff;
- if (Math.Abs(r1 - r2) >= threshold)
- {
- r1 = (int)((amount + 1) * (r1 - r2) + r2);
- if (r1 < 0) r1 = 0;
- if (r1 > 255) r1 = 255;
- }
- if (Math.Abs(g1 - g2) >= threshold)
- {
- g1 = (int)((amount + 1) * (g1 - g2) + g2);
- if (g1 < 0) g1 = 0;
- if (g1 > 255) g1 = 255;
- }
- if (Math.Abs(b1 - b2) >= threshold)
- {
- b1 = (int)((amount + 1) * (b1 - b2) + b2);
- if (b1 < 0) b1 = 0;
- if (b1 > 255) b1 = 255;
- }
- inPixels[index] = (int)(rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1;
- }
- var byteArray = new byte[inPixels.Length * 4];
- for (int i = 0; i < inPixels.Length; i++)
- {
- Array.Copy(BitConverter.GetBytes(inPixels[i]), 0, byteArray, i * 4, 4);
- }
- Bitmap Image = new Bitmap(map.Width, map.Height, PixelFormat.Format32bppArgb);
- var data = ((Bitmap)Image).LockBits(new Rectangle(0, 0, Image.Width, Image.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
- if (data.Stride == Image.Width * 4)
- {
- Marshal.Copy(byteArray, 0, data.Scan0, byteArray.Length);
- }
- else
- {
- for (int i = 0, l = Image.Height; i < l; i++)
- {
- var p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
- Marshal.Copy(byteArray, i * Image.Width * 4, p, Image.Width * 4);
- }
- }
- ((Bitmap)Image).UnlockBits(data);
- return OpenCvSharp.Extensions.BitmapConverter.ToMat((Bitmap)Image);
- }
- /// <summary>
- /// Blur and transpose a block of ARGB pixels.
- /// </summary>
- /// <param name="kernel"></param>
- /// <param name="inPixels"></param>
- /// <param name="outPixels"></param>
- /// <param name="width"></param>
- /// <param name="height"></param>
- /// <param name="alpha"></param>
- /// <param name="premultiply"></param>
- /// <param name="unpremultiply"></param>
- /// <param name="edgeAction"></param>
- public static void ConvolveAndTranspose(Kernel kernel, int[] inPixels, int[] outPixels, int width, int height, bool alpha, bool premultiply, bool unpremultiply, int edgeAction)
- {
- float[] matrix = kernel.GetKernel();
- int cols = kernel.Width;
- int cols2 = cols / 2;
- for (int y = 0; y < height; y++)
- {
- int index = y;
- int ioffset = y * width;
- for (int x = 0; x < width; x++)
- {
- float r = 0, g = 0, b = 0, a = 0;
- int moffset = cols2;
- for (int col = -cols2; col <= cols2; col++)
- {
- float f = matrix[moffset + col];
- if (f != 0)
- {
- int ix = x + col;
- if (ix < 0)
- {
- if (edgeAction == 1)
- ix = 0;
- else if (edgeAction == 2)
- ix = (x + width) % width;
- }
- else if (ix >= width)
- {
- if (edgeAction == 1)
- ix = width - 1;
- else if (edgeAction == 2)
- ix = (x + width) % width;
- }
- int rgb = inPixels[ioffset + ix];
- int pa = (rgb >> 24) & 0xff;
- int pr = (rgb >> 16) & 0xff;
- int pg = (rgb >> 8) & 0xff;
- int pb = rgb & 0xff;
- if (premultiply)
- {
- float a255 = pa * (1.0f / 255.0f);
- pr = (int)(pr * a255);
- pg = (int)(pg * a255);
- pb = (int)(pb * a255);
- }
- a += f * pa;
- r += f * pr;
- g += f * pg;
- b += f * pb;
- }
- }
- if (unpremultiply && a != 0 && a != 255)
- {
- float f = 255.0f / a;
- r *= f;
- g *= f;
- b *= f;
- }
- int ff = (int)(a + 0.5);
- if (ff > 255) ff = 255;
- if (ff < 0) ff = 0;
- int ia = alpha ? ff : 0xff;
- int ir = (int)(r + 0.5);
- if (ir > 255) ir = 255;
- if (ir < 0) ir = 0;
- int ig = (int)(g + 0.5);
- if (ig > 255) ig = 255;
- if (ig < 0) ig = 0;
- int ib = (int)(b + 0.5);
- if (ib > 255) ib = 255;
- if (ib < 0) ib = 0;
- outPixels[index] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
- index += height;
- }
- }
- }
- public static int[] ByteArray(Bitmap map)
- {
- var data = map.LockBits(new Rectangle(0, 0, map.Width, map.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
- var length = map.Width * map.Height * 4;
- byte[] _byteArray = new byte[length];
- if (data.Stride == map.Width * 4)
- {
- Marshal.Copy(data.Scan0, _byteArray, 0, length);
- }
- else
- {
- for (int i = 0, l = map.Height; i < l; i++)
- {
- var p = new IntPtr(data.Scan0.ToInt32() + data.Stride * i);
- Marshal.Copy(p, _byteArray, i * map.Width * 4, map.Width * 4);
- }
- }
- map.UnlockBits(data);
- var intArray = new int[_byteArray.Length / 4];
- for (int i = 0; i < _byteArray.Length; i += 4)
- {
- intArray[i / 4] = BitConverter.ToInt32(_byteArray, i);
- }
- return intArray;
- }
- /// <summary>
- /// 创建一个高斯滤波核
- /// </summary>
- /// <param name="radius">半径</param>
- /// <returns>kernel</returns>
- public static Kernel CreateKernel(float radius)
- {
- var r = (int)Math.Ceiling(radius);
- int rows = r * 2 + 1;
- var matrix = new float[rows];
- float sigma = radius / 3;
- float sigma22 = 2 * sigma * sigma;
- var sigmaPi2 = (float)(2 * Math.PI * sigma);
- var sqrtSigmaPi2 = (float)Math.Sqrt(sigmaPi2);
- float radius2 = radius * radius;
- float total = 0;
- int index = 0;
- for (int row = -r; row <= r; row++)
- {
- float distance = row * row;
- if (distance > radius2)
- matrix[index] = 0;
- else
- matrix[index] = (float)Math.Exp(-(distance) / sigma22) / sqrtSigmaPi2;
- total += matrix[index];
- index++;
- }
- for (int i = 0; i < rows; i++)
- {
- matrix[i] /= total;
- }
- return new Kernel(rows, 1, matrix);
- }
- /// <summary>
- /// 单通道碎屑删除
- /// </summary>
- /// <param name="src"></param>
- /// <returns></returns>
- public unsafe static Mat SingleChannelDebrisRemoval(Mat src, int v = 20)
- {
- Mat labelMat = new Mat();
- Mat stats = new Mat();
- Mat centroids = new Mat();
- try
- {
- original = src;
- //寻找连通分量
- int nonenum = Cv2.ConnectedComponentsWithStats(original, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
- //寻找在范围内需要删除的碎屑
- keyValuePairs.Clear();
- for (int h = 1; h < centroids.Height; h++)
- {
- int areaField1 = stats.At<int>(h, 4);
- if (0 <= areaField1 && areaField1 <= v)
- {
- keyValuePairs.Add(h, 1);
- }
- }
- labelMat.ForEachAsInt32(SingleCommonForEachForInt32);
- }
- catch (Exception ex)
- {
- }
- finally
- {
- keyValuePairs.Clear();
- if (labelMat != null && !labelMat.IsDisposed)
- {
- labelMat.Dispose();
- }
- if (stats != null && !stats.IsDisposed)
- {
- stats.Dispose();
- }
- if (centroids != null && !centroids.IsDisposed)
- {
- centroids.Dispose();
- }
- System.GC.Collect();
- }
- return src;
- }
- private unsafe static void SingleCommonForEachForInt32(int* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- int v = *value;
- if (v > 0 && keyValuePairs.ContainsKey(v))
- {
- original.Set<int>(y, x, 0);
- }
- }
- /// <summary>
- /// 单通道孔洞填充
- /// </summary>
- /// <param name="src"></param>
- /// <param name="vec4b"></param>
- /// <returns></returns>
- public unsafe static Mat SingleChannelHoleFilling(Mat src, Vec4b vec4b)
- {
- vec4B = vec4b;
- //去掉透明层
- Mat mat = src.CvtColor(ColorConversionCodes.BGRA2BGR);
- //填充孔洞
- mat = Tools.FillHole(mat, new Scalar(255 - vec4B.Item0, 255 - vec4B.Item1, 255 - vec4B.Item2));
- src = Tools.FillHole(src, new Scalar(255));
- //循环处理
- mat.ForEachAsVec3b(RGBForEachAsByteForHoleFillingNewWithView);
- if (mat != null && !mat.IsDisposed) mat.Dispose();
- System.GC.Collect();
- return src;
- }
- /*private unsafe static void RGBForEachAsByteForHoleFillingNewWithView(Vec3b* value, int* position)
- {
- int y = position[0];
- int x = position[1];
- if (value->Item0 == 255 && value->Item1 == 255 && value->Item2 == 255)
- {
- value->Item0 = vec4B.Item0;
- value->Item1 = vec4B.Item1;
- value->Item2 = vec4B.Item2;
- }
- else
- {
- value->Item0 = 255;
- value->Item1 = 255;
- value->Item2 = 255;
- }
- }*/
- }
- }
|