123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765 |
- 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 PaintDotNet.Adjust.BaseImage
- {
- /// <summary>
- /// 图像处理基本工具
- /// </summary>
- public static class BaseTools
- {
- public static int[] table =
- //0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1
- {0,0,0,0,0,0,1,3,0,0,3,1,1,0,1,3,0,0,0,0,0,0,0,0,0,0,2,0,3,0,3,3,
- 0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,3,0,2,2,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 2,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,2,0,
- 0,0,3,1,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
- 3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 2,3,1,3,0,0,1,3,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 2,3,0,1,0,0,0,1,0,0,0,0,0,0,0,0,3,3,0,1,0,0,0,0,2,2,0,0,2,0,0,0};
- // 2013/12/02: 16,6 2->0
- // 2013/12/02: 24,5 0->2
- public static int[] table2 =
- //0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1
- {0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,2,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- /// <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>
- /// 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;
- }
- }
- }
- /// <summary>
- /// 参考https://blog.csdn.net/ls9512/article/details/50001753
- /// RgbToHsv
- /// </summary>
- /// <param name="prgb"></param>
- /// <param name="H"></param>
- /// <param name="S"></param>
- /// <param name="V"></param>
- public static void RgbToHsv(Vec3b prgb, out double H, out double S, out double V)
- {
- float min, max, tmp;
- float R = prgb[2] * 1.0f / 255, G = prgb[1] * 1.0f / 255, B = prgb[0] * 1.0f / 255;
- tmp = Math.Min(R, G);
- min = Math.Min(tmp, B);
- tmp = Math.Max(R, G);
- max = Math.Max(tmp, B);
- // H
- H = 0;
- if (max == min)
- {
- H = 0;
- }
- else if (max == R && G > B)
- {
- H = 60 * (G - B) * 1.0f / (max - min) + 0;
- }
- else if (max == R && G < B)
- {
- H = 60 * (G - B) * 1.0f / (max - min) + 360;
- }
- else if (max == G)
- {
- H = H = 60 * (B - R) * 1.0f / (max - min) + 120;
- }
- else if (max == B)
- {
- H = H = 60 * (R - G) * 1.0f / (max - min) + 240;
- }
- // S
- if (max == 0)
- {
- S = 0;
- }
- else
- {
- S = (max - min) * 1.0f / max;
- }
- // V
- V = max;
- //return new ColorHSV((int)H, (int)(S * 255), (int)(V * 255));
- }
- public static void RGBtoHLS(Vec3b prgb, out double H, out double L, out double S)
- {
- double n_cmax = Math.Max(prgb[0], Math.Max(prgb[1], prgb[2]));
- double n_cmin = Math.Min(prgb[0], Math.Min(prgb[1], prgb[2]));
- L = (n_cmax + n_cmin) / 2.0 / 255.0;
- if (n_cmax == n_cmin)
- {
- S = H = 0.0;
- return;
- }
- double r = prgb[2] / 255.0;
- double g = prgb[1] / 255.0;
- double b = prgb[0] / 255.0;
- double cmax = n_cmax / 255.0;
- double cmin = n_cmin / 255.0;
- double delta = cmax - cmin;
- if (L < 0.5)
- S = delta / (cmax + cmin);
- else
- S = delta / (2.0 - cmax - cmin);
- if (prgb[2] == n_cmax)
- H = (g - b) / delta;
- else if (prgb[1] == n_cmax)
- H = 2.0 + (b - r) / delta;
- else
- H = 4.0 + (r - g) / delta;
- H /= 6.0;
- if (H < 0.0)
- H += 1.0;
- }
- public static Vec3b HLStoRGB(double H, double L, double S)
- {
- if (S < 1.19209290E-07F)//== 0
- {
- Vec3b r = new Vec3b();
- r[0] = (byte)(L * 255);
- r[1] = (byte)(L * 255);
- r[2] = (byte)(L * 255);
- return r;
- }
- double m1, m2;
- if (L < 0.5)
- m2 = L * (1.0 + S);
- else
- m2 = L + S - L * S;
- m1 = 2.0 * L - m2;
- Vec3b r1 = new Vec3b();
- r1[2] = (byte)(__HLS_Value(m1, m2, H * 6.0 + 2.0) * 255);
- if (r1[2] < 0) r1[2] = 0; if (r1[2] > 255) r1[2] = 255;
- r1[1] = (byte)(__HLS_Value(m1, m2, H * 6.0) * 255);
- if (r1[1] < 0) r1[1] = 0; if (r1[1] > 255) r1[1] = 255;
- r1[0] = (byte)(__HLS_Value(m1, m2, H * 6.0 - 2.0) * 255);
- if (r1[0] < 0) r1[0] = 0; if (r1[0] > 255) r1[0] = 255;
- return r1;
- }
- public static double __HLS_Value(double m1, double m2, double h)
- {
- if (h > 6.0)
- h -= 6.0;
- else if (h < 0.0)
- h += 6.0;
- if (h < 1.0)
- return m1 + (m2 - m1) * h;
- else if (h < 3.0)
- return m2;
- else if (h < 4.0)
- return m1 + (m2 - m1) * (4.0 - h);
- return m1;
- }
- /// <summary>
- /// Bitmap转int数组
- /// </summary>
- /// <param name="map"></param>
- /// <returns></returns>
- 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="mat"></param>
- /// <returns></returns>
- public static bool DetermineBinaryImage(Mat mat)
- {
- for (int o = 0; o < mat.Height; o++)
- {
- for (int p = 0; p < mat.Width; p++)
- {
- byte v = mat.At<byte>(o, p);
- if(v!=255 && v != 0)
- {
- return false;
- }
- }
- }
- return true;
- }
- /// <summary>
- /// 根据图像的直方图判断是否是二个颜色的图
- /// </summary>
- /// <param name="mat"></param>
- /// <returns></returns>
- public static bool DetermineBinaryImageByHist(Mat mat)
- {
- //根据灰度图的直方图计算是否是二值图
- Mat[] mats0 = new Mat[] { mat };
- int[] channels0 = new int[] { 0 };
- int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
- Rangef[] range = new Rangef[1];
- range[0] = new Rangef(0.0F, 256.0F);
- Mat hist = new Mat();
- Cv2.CalcHist(mats0, channels0, new Mat(), hist, 1, histsize, range);
- int value = 0;
- for (int i = 0; i < 256; i++)
- {
- //取每个bin的数目
- int temp = (int)(hist.At<float>(i, 0));
- if (temp > 0)
- value++;
- }
- return value == 2;
- }
- /// <summary>
- /// 收缩图像
- /// </summary>
- /// <param name="ip"></param>
- /// <param name="ip2"></param>
- /// <param name="hasEdgePixels"></param>
- /// <returns></returns>
- public static Mat shrink(Mat ip, Mat ip2, bool hasEdgePixels)
- {
- if (hasEdgePixels)
- {
- int width = ip.Width;
- int height = ip.Height;
- for (int y = 0; y < height; y++)
- for (int x = 0; x < width; x++)
- ip.Set<byte>(y, x, ip2.At<byte>(y + 1, x + 1));
- }
- return ip;
- }
- /// <summary>
- /// 阴影校正功能里面,用来进行行列处理的方法
- /// </summary>
- /// <param name="I_OUT"></param>
- /// <param name="threshold"></param>
- /// <returns></returns>
- public static Mat ImageSmoothIIR(Mat I_OUT, double threshold)
- {
- /*int M = I_OUT.Height;
- int N = I_OUT.Width;
- for (int P = 1; P < M; P++)
- {
- I_OUT.Row[P] = threshold * 1.0f * (I_OUT.Row[P - 1] - I_OUT.Row[P]) + I_OUT.Row[P];
- }
- for (int P = M - 2; P > -1; P--)
- {
- I_OUT.Row[P] = threshold * 1.0f * (I_OUT.Row[P + 1] - I_OUT.Row[P]) + I_OUT.Row[P];
- }
- for (int L = 1; L < N; L++)
- {
- I_OUT.Col[L] = threshold * 1.0f * (I_OUT.Col[L - 1] - I_OUT.Col[L]) + I_OUT.Col[L];
- }
- for (int L = N - 2; L > -1; L--)
- {
- I_OUT.Col[L] = threshold * 1.0f * (I_OUT.Col[L + 1] - I_OUT.Col[L]) + I_OUT.Col[L];
- }
- return I_OUT;*/
- Mat temp = null;
- int M = I_OUT.Height;
- int N = I_OUT.Width;
- for (int P = 1; P < M; P++)
- {
- temp = (threshold * 1.0f * (I_OUT.Row(P - 1) - I_OUT.Row(P)) + I_OUT.Row(P));
- temp.CopyTo(I_OUT.Row(P));
- }
- for (int P = M - 2; P > -1; P--)
- {
- temp = (threshold * 1.0f * (I_OUT.Row(P + 1) - I_OUT.Row(P)) + I_OUT.Row(P));
- temp.CopyTo(I_OUT.Row(P));
- }
- for (int L = 1; L < N - 1; L++)
- {
- temp = (threshold * 1.0f * (I_OUT.Col(L - 1) - I_OUT.Col(L)) + I_OUT.Col(L));
- temp.CopyTo(I_OUT.Col(L));
- }
- for (int L = N - 2; L > -1; L--)
- {
- temp = (threshold * 1.0f * (I_OUT.Col(L + 1) - I_OUT.Col(L)) + I_OUT.Col(L));
- temp.CopyTo(I_OUT.Col(L));
- }
- return I_OUT;
- }
- /// <summary>
- /// 引射线法判断点是否在多边形内部(以该点为起点沿x轴负方向做一条射线)
- /// </summary>
- /// <param name="p"></param>
- /// <param name="vPoint"></param>
- /// <returns></returns>
- public static bool isPointInPolygon(System.Drawing.Point p, List<System.Drawing.PointF> vPoint)
- {
- int i, j = vPoint.Count - 1;
- bool inside = false;
- double x = p.X;
- double y = p.Y;
- for (i = 0; i < vPoint.Count; i++)
- {
- if (((vPoint[i].Y < y && vPoint[j].Y >= y) || (vPoint[i].Y >= y && vPoint[j].Y < y)) && (vPoint[i].X <= x || vPoint[j].X <= x))
- {
- double dTmp = vPoint[i].X + (y - vPoint[i].Y) / (vPoint[j].Y - vPoint[i].Y) * (vPoint[j].X - vPoint[i].X);
- bool bTmp;
- if (dTmp == x) //点在多边形的边上,也算在多边形内
- {
- //count = 1;
- return true;
- }
- else
- bTmp = (dTmp < x);
- inside ^= bTmp;
- //if (bTmp)
- //count++;
- }
- j = i;
- }
- return inside;
- }
- /// <summary>
- /// 判断点是否在椭圆内
- /// </summary>
- /// <param name="point"></param>
- /// <param name="centerPoint"></param>
- /// <returns></returns>
- public static bool isPointInOval(System.Drawing.Point point, System.Drawing.PointF centerPoint, float xaxis, float yaxis)
- {
- double v = Math.Pow(centerPoint.X - point.X, 2) / Math.Pow(xaxis, 2) + Math.Pow(centerPoint.Y - point.Y, 2) / Math.Pow(yaxis, 2);
- return v < 1;
- }
- /// <summary>
- /// System.Drawing.Point转OpenCvSharp.Point
- /// </summary>
- /// <param name="points1"></param>
- /// <param name="points2"></param>
- /// <returns></returns>
- public static List<OpenCvSharp.Point> pointToPoint(List<System.Drawing.PointF> points)
- {
- List<OpenCvSharp.Point> points1 = new List<OpenCvSharp.Point>();
- foreach(System.Drawing.PointF point in points)
- {
- points1.Add(new OpenCvSharp.Point(point.X, point.Y));
- }
- return points1;
- }
- /// <summary>
- /// 判断mat是否相同
- /// </summary>
- /// <param name="a"></param>
- /// <param name="b"></param>
- /// <returns></returns>
- public static bool matEqual(Mat a, Mat b) {
- Mat temp = new Mat();
- Cv2.BitwiseXor(a, b, temp);
- Mat[] mats = temp.Split();
- int a1 = Cv2.CountNonZero(mats[0]);
- int a2 = Cv2.CountNonZero(mats[1]);
- int a3 = Cv2.CountNonZero(mats[2]);
- int a4 = Cv2.CountNonZero(mats[3]);
- return (a1+ a2+ a3+ a4) ==0;
- }
- /// <summary>
- /// 图像旋转
- /// </summary>
- /// <param name="src"></param>
- /// <param name="dst"></param>
- /// <param name="angle"></param>
- /// <param name="flags"></param>
- public static void ImageRotate(Mat src, Mat dst, float angle, InterpolationFlags flags)
- {
- Mat dst1 = new Mat();
- Point2f center = new Point2f(src.Cols / 2, src.Rows / 2);
- Mat rot = Cv2.GetRotationMatrix2D(center, -angle, 1);
- Size2f s2f = new Size2f(src.Size().Width, src.Size().Height);
- Rect box = new RotatedRect(new Point2f(0, 0), s2f, -angle).BoundingRect();
- double xx = rot.At<double>(0, 2) + box.Width / 2 - src.Cols / 2;
- double zz = rot.At<double>(1, 2) + box.Height / 2 - src.Rows / 2;
- rot.Set(0, 2, xx);
- rot.Set(1, 2, zz);
- //对图片进行仿射变换
- Cv2.WarpAffine(src, dst1, rot, box.Size, flags);
- dst1.CopyTo(dst);
- }
- /// <summary>
- /// 获取不相近的随机颜色
- /// </summary>
- public static Color GetRandomColor(Color color)
- {
- double H, L, S;
- Vec3b vec3B = new Vec3b();
- vec3B.Item0 = color.B;
- vec3B.Item1 = color.G;
- vec3B.Item1 = color.R;
- RGBtoHLS(vec3B, out H, out L, out S);
- double H1=0, L1=0, S1=0;
- for (var i = 0; i < 1; i++)
- {
- double[] ret = RandomHsl();
- // 颜色相邻颜色差异须大于 0.25
- if (i > 0 && Math.Abs(ret[0] - H) < 0.25)
- {
- i--;
- continue; // 重新获取随机色
- }
- ret[1] = 0.7 + (ret[1] * 0.2); // [0.7 - 0.9] 排除过灰颜色
- ret[2] = 0.4 + (ret[2] * 0.4); // [0.4 - 0.8] 排除过亮过暗色
- H1 = ret[0];
- S1 = ret[1];
- L1 = ret[2];
- }
- Vec3b v = HLStoRGB(H1, L1, S1);
- return Color.FromArgb(v.Item2, v.Item1, v.Item0);
- }
- public static double[] RandomHsl()
- {
- Random random = new Random();
- double[] hsl = new double[3];
- var H = random.NextDouble();
- var S = random.NextDouble();
- var L = random.NextDouble();
- hsl[0] = H;
- hsl[1] = S;
- hsl[2] = L;
- return hsl;
- }
- /// <summary>
- /// 将bitmap转透明,需要四个通道的bitmap
- /// </summary>
- /// <param name="bitmap"></param>
- /// <returns></returns>
- public static Bitmap BitmapToTransparent(Bitmap bitmap)
- {
- OpenCvSharp.Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
- if(mat.Type() == MatType.CV_8UC4)
- {
- Mat[] mats = mat.Split();
- mats[3].SetTo(new Scalar(0));
- Cv2.Merge(mats, mat);
- return OpenCvSharp.Extensions.BitmapConverter.ToBitmap(mat);
- }
- return bitmap;
- }
- /// <summary>
- /// 形态学孔洞填充
- /// </summary>
- /// <param name="srcBw">二值图0/255</param>
- /// <returns></returns>
- public static Mat FillHole(Mat srcBw, Scalar scalar)
- {
- OpenCvSharp.Size m_Size = srcBw.Size();
- //创建扩展边界的图像
- Mat temp = Mat.Zeros(m_Size.Height + 2, m_Size.Width + 2, srcBw.Type());
- srcBw.CopyTo(new Mat(temp, new Range(1, m_Size.Height + 1), new Range(1, m_Size.Width + 1)));
- //new OpenCvSharp.Point(0, 0)
- Cv2.FloodFill(temp, new OpenCvSharp.Point(0, 0), scalar);
- //裁剪扩展边界的图像
- Mat cutImg = new Mat();
- new Mat(temp, new Range(1, m_Size.Height + 1), new Range(1, m_Size.Width + 1)).CopyTo(cutImg);
- return srcBw | (~cutImg);
- }
- /// <summary>
- /// 返回合并后的图片
- /// 主要适用于四通道合并为三通道
- /// </summary>
- /// <param name="arr"></param>
- /// <returns></returns>
- public static Mat MergeMatFromMatArr(Mat[] arr)
- {
- Mat[] mats = new Mat[3];
- mats[0] = arr[0];
- mats[1] = arr[1];
- mats[2] = arr[2];
- Mat dst = new Mat();
- Cv2.Merge(mats, dst);
- return dst;
- }
- /// <summary>
- /// 形态学提取连通分量
- /// </summary>
- /// <param name="src">需要0/1的二值图</param>
- /// <param name="iseight">true 8连通 / false 4连通</param>
- /// <param name="points">各个连通区域的种子点的坐标集合</param>
- /// <param name="nums">各个连通区域的像素个数集合</param>
- public static void MorphologExConnComponents(Mat src, bool iseight, out List<OpenCvSharp.Point> points, out List<int> nums)
- {
- points = new List<OpenCvSharp.Point>();
- nums = new List<int>();
- Mat structelement;
- if (iseight)
- structelement = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
- else
- structelement = Cv2.GetStructuringElement(MorphShapes.Cross, new OpenCvSharp.Size(3, 3));
- //dst = Mat.Ones(src.Size(), src.Type());
- Mat tmp = Mat.Ones(src.Size(), src.Type()); // save last reuslt image
- //Mat img = Mat.Ones(src.Size(), src.Type()); //image B
- int labelnum = 0; //label of connected component
- Mat backupsrc = new Mat();
- src.CopyTo(backupsrc);
- for (int i = 0; i < backupsrc.Rows; i++)
- {
- for (int j = 0; j < backupsrc.Cols; j++)
- {
- if (backupsrc.At<byte>(i, j) == 255)
- {
- Mat img = Mat.Ones(src.Size(), src.Type());
-
- img.CopyTo(tmp); img.Set<byte>(i, j, 255);
- labelnum++;
- while (true)
- {
- Cv2.Dilate(img, img, structelement);
- Cv2.BitwiseAnd(img, src, img);
- if (Cv2.CountNonZero(img - tmp) == 0)
- break;
- img.CopyTo(tmp);
- }
- //Cv2.ImShow("xx" + labelnum, img);
- // int xx = Cv2.CountNonZero(img);
- //System.Console.WriteLine(labelnum +"、" +i+ "、" + j +":" + xx);
- int hh = 0;
- //label the connected component
- for (int r = 0; r < img.Rows; r++)
- {
- for (int c = 0; c < img.Cols; c++)
- {
- if (img.At<byte>(r, c) == 255)
- {
- hh++;
- backupsrc.Set<byte>(r, c, 0);
- //dst.Set<int>(r, c, labelnum);
- }
- }
- }
- points.Add(new OpenCvSharp.Point(j, i));
- nums.Add(hh);
- //System.Console.WriteLine(labelnum + ":" + hh);
- }
- }
- }
- //return labelnum;
- }
- public static Mat MergeMatFromMatArr(Mat src, Vec4b vec4B)
- {
- Mat[] arr = src.Split();
- Mat apa = arr[3].Clone();
- apa = apa * 1/255;
- arr[0] = apa * vec4B.Item0;
- arr[1] = apa * vec4B.Item1;
- arr[2] = apa * vec4B.Item2;
- Cv2.Merge(arr, src);
- return src;
- }
- }
- }
|