Commit bc6e4f45 cuiyadong

对粘连blob分组

1 个父辈 b290e77b
正在显示 1 个修改的文件 包含 201 行增加215 行删除
...@@ -40,7 +40,7 @@ namespace Acc.Img ...@@ -40,7 +40,7 @@ namespace Acc.Img
buff[n++] = bb[0]; buff[n++] = bb[0];
buff[n++] = bb[1]; buff[n++] = bb[1];
buff[n++] = bb[0]; buff[n++] = bb[0];
buff[n++] = bb[1]; buff[n++] = bb[1];
} }
Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format48bppRgb); Bitmap bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format48bppRgb);
...@@ -446,7 +446,7 @@ namespace Acc.Img ...@@ -446,7 +446,7 @@ namespace Acc.Img
} }
private static CvBlobs AutoThreshBlobs(ref Mat imageMat,int blobArea,out int standArea,RadiusPt radiusPt,RadiusPt radiusPtOut) private static CvBlobs AutoThreshBlobs(ref Mat imageMat,int blobArea,out int standArea,RadiusPt radiusPt,RadiusPt radiusPtOut)
{ {
Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda
Mat hist = new Mat();//用来接收直方图 Mat hist = new Mat();//用来接收直方图
int[] channels = new int[] { 0 };//一个通道,初始化为通道0 int[] channels = new int[] { 0 };//一个通道,初始化为通道0
...@@ -456,6 +456,7 @@ namespace Acc.Img ...@@ -456,6 +456,7 @@ namespace Acc.Img
range[0].End = 256.0F;//到256结束(不含) range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码 Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range);//计算灰度图,dim为1 1维 Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range);//计算灰度图,dim为1 1维
double total = 0; double total = 0;
for (int i = 0; i < 256; i++)//灰度值总数量 for (int i = 0; i < 256; i++)//灰度值总数量
{ {
...@@ -485,7 +486,7 @@ namespace Acc.Img ...@@ -485,7 +486,7 @@ namespace Acc.Img
int avgIndex = (startIndex + endIndex) / 2; int avgIndex = (startIndex + endIndex) / 2;
//avgIndex = GetIntermodesThreshold(hist); //int avgIndex = GetIntermodesThreshold(hist);
Mat threshMat = new Mat(); Mat threshMat = new Mat();
Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv);
...@@ -924,28 +925,41 @@ namespace Acc.Img ...@@ -924,28 +925,41 @@ namespace Acc.Img
private static List<CircleStruct> resultList = new List<CircleStruct>(); private static List<CircleStruct> resultList = new List<CircleStruct>();
private static List<List<CircleStruct>> spitList = new List<List<CircleStruct>>(); private static List<List<CircleStruct>> spitList = new List<List<CircleStruct>>();
private static CircleStruct circleStruct = new CircleStruct(); private static CircleStruct circleStruct = new CircleStruct();
public static void findCircleInBlobNew(double[,] matDistanceArr, CvBlobs blobs, CvBlob blob, Point2d reelCenter, double oneBlobWidth = -1, double oneBlobRadius = -1) //private static List<CircleStruct> sampList = new List<CircleStruct>();
{ /// <summary>
/// 粘连blob分组
/// </summary>
/// <param name="matDistanceArr"></param>
/// <param name="blobs"></param>
/// <param name="blob"></param>
/// <param name="reelCenter"></param>
/// <param name="oneBlobWidth"></param>
/// <param name="oneBlobRadius"></param>
/// <returns></returns>
public static List<List<CircleStruct>> findCircleInBlobNew(double[,] matDistanceArr, CvBlobs blobs, CvBlob blob, Point2d reelCenter, double oneBlobWidth = -1, double oneBlobRadius = -1)
{
resultList.Clear(); resultList.Clear();
for (int x = blob.MinX; x < blob.MaxX; x++) spitList.Clear();
for (int y = blob.MinY; y < blob.MaxY; y++)
{ {
for (int y = blob.MinY; y < blob.MaxY; y++) for (int x = blob.MinX; x < blob.MaxX; x++)
{ {
double distance = matDistanceArr[x, y]; double distance = matDistanceArr[x, y];
if (distance > 0) if (distance > 0)
{ {
int label = blobs.GetLabel(x, y); int label = blobs.GetLabel(x, y);
if (label != blob.Label) if (label != blob.Label)
{ {
continue; continue;
} }
else else
{ {
if (distance>=oneBlobRadius*0.8) if (distance >= oneBlobRadius*2/3)
{ {
circleStruct.centerPt.X = x; circleStruct.centerPt.X = x;
circleStruct.centerPt.Y = y; circleStruct.centerPt.Y = y;
circleStruct.radius = distance; circleStruct.radius = oneBlobRadius*2/3;
if (startI == -1) if (startI == -1)
{ {
startI = 1; startI = 1;
...@@ -956,12 +970,7 @@ namespace Acc.Img ...@@ -956,12 +970,7 @@ namespace Acc.Img
bool intersectionB = false; bool intersectionB = false;
foreach (CircleStruct item in resultList) foreach (CircleStruct item in resultList)
{ {
//if (Math.Abs(item.centerPt.DistanceTo(new OpenCvSharp.Point(reelCenter.X,reelCenter.Y))-circleStruct.centerPt.DistanceTo(new OpenCvSharp.Point(reelCenter.X, reelCenter.Y)))<=oneBlobWidth) if (item.centerPt.DistanceTo(circleStruct.centerPt) <= item.radius)
//{
// intersectionB = true;
// break;
//}
if (item.centerPt.DistanceTo(circleStruct.centerPt)<item.radius+distance)
{ {
intersectionB = true; intersectionB = true;
break; break;
...@@ -972,27 +981,56 @@ namespace Acc.Img ...@@ -972,27 +981,56 @@ namespace Acc.Img
resultList.Add(circleStruct); resultList.Add(circleStruct);
} }
} }
} }
} }
} }
} }
}
//分离 }
//分离
while (resultList.Count != 0) while (resultList.Count != 0)
{ {
List<CircleStruct> sampList = new List<CircleStruct>();
CircleStruct itemC = new CircleStruct();
//sampList.Clear();
bool startB = false;
for (int i = 0; i < resultList.Count; i++)
{
if (!startB)
{
startB = true;
sampList.Add(resultList[i]);
itemC = resultList[i];
resultList.RemoveAt(i);
i -= 1;
}
else
{
for (int j = 0; j < sampList.Count; j++)
{
double distan = Math.Abs(resultList[i].centerPt.DistanceTo(new OpenCvSharp.Point(reelCenter.X, reelCenter.Y)) - sampList[j].centerPt.DistanceTo(new OpenCvSharp.Point(reelCenter.X, reelCenter.Y)));
if (distan <= oneBlobRadius*1.78 && resultList[i].centerPt.DistanceTo(itemC.centerPt) <= oneBlobWidth*1.1)
{
sampList.Add(resultList[i]);
resultList.RemoveAt(i);
i -= 1;
break;
}
else
{
break;
}
}
}
}
spitList.Add(sampList);
if (resultList.Count < spitList[spitList.Count - 1].Count / 9)
break;
} }
return spitList;
} }
/// <summary> /// <summary>
...@@ -1071,11 +1109,13 @@ namespace Acc.Img ...@@ -1071,11 +1109,13 @@ namespace Acc.Img
} }
//平均半径 //平均半径
double averRadius = averItem.Sum(a => a.circles.Sum(b => b.radius)) / averItem.Sum(a => a.circles.Count); double averRadius = averItem.Sum(a => a.circles.Sum(b => b.radius)) / averItem.Sum(a => a.circles.Count);
maxRadius = averRadius*3/2; //maxRadius = averRadius*3/2;
maxRadius = averRadius;
//放大宽度,防止误判断 //放大宽度,防止误判断
//maxWidth = maxWidth * 1.6; //maxWidth = maxWidth * 1.6;
Console.WriteLine("Start count"); Console.WriteLine("Start count");
int totalCount = 0; int totalCount = 0;
bool end = false;
foreach (CvBlob blob in blobs.Values) foreach (CvBlob blob in blobs.Values)
{ {
int count = BlobHasItem(avgArea, blob); int count = BlobHasItem(avgArea, blob);
...@@ -1107,216 +1147,160 @@ namespace Acc.Img ...@@ -1107,216 +1147,160 @@ namespace Acc.Img
{ {
continue; continue;
} }
////多个元器件,查找 所有圆 //////多个元器件,查找 所有圆
SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius); //SplitItem item = findCircleInBlob(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//对所有圆进行分组 ////对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter); //List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter);
//foreach (List<Circle> groupCircle in groupCircles)
//{
// if (groupCircle.Count == 0)
// {
// continue;
// }
// Circle c = groupCircle[0];
// srcMat.Circle(c.x, c.y, (int)c.radius / 2, Scalar.Yellow);
// totalCount = totalCount + 1;
// //foreach (Circle cg in groupCircle)
// //{
// // srcMat.Circle(cg.x, cg.y, (int)cg.radius, color);
// //}
//}
//Scalar color = Scalar.RandomColor(); List<List<CircleStruct>> resultList = findCircleInBlobNew(distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//blob.Contour.Render(srcMat, color); foreach (List<CircleStruct> item in resultList)
{
srcMat.Circle(item[0].centerPt, (int)item[0].radius, Scalar.Yellow);
totalCount = totalCount + 1;
}
}
}
Cv2.PutText(srcMat, totalCount + "", new OpenCvSharp.Point(reelCenter.X-40, reelCenter.Y+30), HersheyFonts.HersheySimplex, 1.0, Scalar.LightGreen);
Console.WriteLine("===========" + totalCount);
return totalCount;
}
foreach (List<Circle> groupCircle in groupCircles) private static List<CircleStruct> GetMaxDistance(CvBlob item, double[,] distanceArr, CvBlobs blobs)
{
double maxDistance = -1;
double standerd = -1;
int maxX = -1;
int maxY = -1;
CircleStruct pR = new CircleStruct();
List<CircleStruct> pTList = new List<CircleStruct>();
bool selectB = false;
while (true)
{
bool blobB = false;
bool threreIs = false;
for (int Y = item.MinY; Y < item.MaxY; Y++)
{
for (int X = item.MinX; X < item.MaxX; X++)
{ {
if (groupCircle.Count == 0) double distance = distanceArr[X, Y];
if (item.Label != blobs.GetLabel(X, Y))
{ {
continue; continue;
} }
Circle c = groupCircle[0]; if (!selectB)
srcMat.Circle(c.x, c.y, (int)c.radius / 2, Scalar.Yellow); {
totalCount = totalCount + 1; if (maxDistance == -1)
//foreach (Circle cg in groupCircle) {
//{ if (distance < 0)
// srcMat.Circle(cg.x, cg.y, (int)c.radius, color); {
//} continue;
}
maxDistance = distance;
maxX = X;
maxY = Y;
pR.centerPt.X = X;
pR.centerPt.Y = Y;
pR.radius = distance;
blobB = true;
}
else
{
if (maxDistance < distance)
{
maxDistance = distance;
maxX = X;
maxY = Y;
pR.centerPt.X = X;
pR.centerPt.Y = Y;
pR.radius = distance;
blobB = true;
}
}
}
else
{
if (distance > maxDistance * 0.7)
{
foreach (var singleBlob in pTList)
{
if (singleBlob.centerPt.DistanceTo(new OpenCvSharp.Point(X, Y)) < singleBlob.radius + distance)
{
threreIs = true;
break;
}
}
if (threreIs)
{
threreIs = false;
continue;
}
standerd = distance;
pR.centerPt.X = X;
pR.centerPt.Y = Y;
pR.radius = distance;
blobB = true;
}
}
} }
} }
}
Cv2.PutText(srcMat, totalCount + "", new OpenCvSharp.Point(reelCenter.X-40, reelCenter.Y+30), HersheyFonts.HersheySimplex, 1.0, Scalar.LightGreen);
Console.WriteLine("===========" + totalCount);
return totalCount;
} selectB = true;
if (!blobB)
{
break;
}
pTList.Add(pR);
}
return pTList;
////TODO: 测试距离变换,用后删除 }
//public static Image DistanceTransform(Image image)
//{
// Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
// Mat gray = new Mat();
// Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY);
// ////开运算
// Mat k1 = Mat.Ones(new OpenCvSharp.Size(1, 1), MatType.CV_8UC1);
// Cv2.MorphologyEx(gray, gray, MorphTypes.Open, k1, new OpenCvSharp.Point(0, 0), 3);
// Mat distanceMat = new Mat();
// Mat labels = new Mat() ;
// Cv2.DistanceTransform(gray, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3) ;
// Cv2.Normalize(distanceMat, gray, 0, 255, NormTypes.MinMax);
// gray.ConvertTo(gray, MatType.CV_8UC1);
// Cv2.Threshold(gray, gray, 0, 255, ThresholdTypes.Otsu);
// Mat colorImg = Mat.Zeros(gray.Size(), MatType.CV_8UC3);
// Cv2.ConnectedComponents(gray, labels, PixelConnectivity.Connectivity8);
// Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
// for(int y=0;y<labels.Rows; y++)
// {
// for (int x = 0; x < labels.Cols; x++)
// {
// int label = labels.At<int>(y, x);
// float distance = distanceMat.At<float>(y, x);
// SplitItem item = new SplitItem();
// if (blobCircles.ContainsKey(label))
// {
// item = blobCircles[label];
// }
// if (distance > item.currentMaxRadius)
// {
// item.currentMaxRadius = distance;
// item.centerX = x;
// item.centerY = y;
// }
// blobCircles[label] = item;
// byte b = (byte)(label % 255);
// byte g = 0;
// if (b < 128 && b>0)
// {
// g = (byte)(255 - b);
// }
// Vec3b color = new Vec3b(b,g,0);
// colorImg.Set<Vec3b>(y, x, color);
// }
// }
// foreach (SplitItem circle in blobCircles.Values)
// {
// circle.calOneItem(-1);
// }
// while (true)
// {
// for (int y = 0; y < labels.Rows; y++)
// {
// for (int x = 0; x < labels.Cols; x++)
// {
// int label = labels.At<int>(y, x);
// if (label == 0) continue;
// SplitItem item = new SplitItem();
// if (blobCircles.ContainsKey(label))
// {
// item = blobCircles[label];
// }
// if (!item.isEnd)
// {
// double distance = distanceMat.At<float>(y, x);
// //此Blob未结束
// // bool validPoint = item.isValidPoint(x, y);
// bool validPoint = false;
// if (validPoint)
// {
// if (distance > item.currentMaxRadius)
// {
// item.currentMaxRadius = distance;
// item.centerX = x;
// item.centerY = y;
// blobCircles[label] = item;
// }
// }
// }
// }
// }
// bool needContinue = false;
// foreach (SplitItem circle in blobCircles.Values)
// {
// circle.calOneItem();
// if (!circle.isEnd)
// {
// needContinue = true;
// }
// }
// if (!needContinue)
// {
// break;
// }
// }
// int totalCount = 0;
// foreach (SplitItem item in blobCircles.Values)
// {
// foreach(Circle circle in item.circles)
// {
// Cv2.Circle(colorImg, circle.x, circle.y, (int)circle.radius,Scalar.White);
// totalCount++;
// }
// }
// Console.WriteLine("Total: " + totalCount);
// return BitmapConverter.ToBitmap(colorImg);
// //dist.SaveImage("d:\\image\\dsitdist1.jpg");
// //Cv2.Threshold(dist, dist, 79, 255, ThresholdTypes.Binary);
// //Cv2.CvtColor(dist,dist,ColorConversionCodes.BGRA2BGR);
// //dist.ConvertTo(dist, MatType.CV_8UC1);
// //image = BitmapConverter.ToBitmap(dist);
// //return image;
//}
public static int GetGrayValue(ref Image image, int markX, int markY) public static int GetGrayValue(ref Image image, int markX, int markY)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
RadiusPt radiusPt, radiusPtOut; RadiusPt radiusPt, radiusPtOut;
GetCenter(imageMat, out radiusPt); GetCenter(imageMat, out radiusPt);
GetOutContour(imageMat, out radiusPtOut); GetOutContour(imageMat, out radiusPtOut);
Mat grayMat = new Mat(); Mat grayMat = new Mat();
Mat thresholdMat = new Mat(); Mat thresholdMat = new Mat();
int minThreshold = -1; int minThreshold = -1;
int sampThreshold = -1, blobNum = -1;
double minArea, maxArea, proportion=0;
CvBlobs blobs = new CvBlobs(); CvBlobs blobs = new CvBlobs();
Cv2.CvtColor(imageMat,imageMat,ColorConversionCodes.BGRA2BGR); //imageMat.SaveImage("d:\\image\\test\\image.jpg");
//imageMat = new Mat("d:\\image\\test\\image.jpg");
Cv2.CvtColor(imageMat, grayMat, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(imageMat, grayMat, ColorConversionCodes.RGB2GRAY);
for (int i = 0; i < 2; i++) Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.BGRA2BGR);
{ Mat[] mats = new Mat[] { grayMat };//一张图片,初始化为panda
if (i == 0) //Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda
{ Mat hist = new Mat();//用来接收直方图
sampThreshold = 151; int[] channels = new int[] { 0 };//一个通道,初始化为通道0
} int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
else Rangef[] range = new Rangef[1];//一个通道,值范围
{ range[0].Start = 0.0F;//从0开始(含)
sampThreshold = 161; range[0].End = 256.0F;//到256结束(不含)
} Mat mask = new Mat();//不做掩码
Cv2.Threshold(grayMat, thresholdMat, sampThreshold, 255, ThresholdTypes.BinaryInv); Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range, true, false);//计算灰度图,dim为1 1维
Cv2.MedianBlur(thresholdMat, thresholdMat, 7); minThreshold = GetIntermodesThreshold(hist);
blobs.Label(thresholdMat);
List<CvBlob> blobL = blobs.Values.Where(a => a.Area > 3 && a.Centroid.DistanceTo(radiusPtOut.pt) > radiusPt.radius && a.Centroid.DistanceTo(radiusPtOut.pt) < radiusPtOut.radius).ToList();
blobL.Sort((a, b) => a.Area.CompareTo(b.Area));
if (blobL.Count == 0)
{
continue;
}
minArea = blobL[0].Area;
maxArea = blobL[blobL.Count - 1].Area;
if (i == 0)
{
blobNum = blobL.Count();
proportion = maxArea / minArea;
}
else
{
if (blobNum > blobL.Count && proportion < maxArea / minArea||blobL.Count<100)
{
minThreshold = 151;
}
else
{
minThreshold = 161;
}
}
}
Cv2.Threshold(grayMat, thresholdMat, minThreshold, 255, ThresholdTypes.BinaryInv); Cv2.Threshold(grayMat, thresholdMat, minThreshold, 255, ThresholdTypes.BinaryInv);
blobs.Label(thresholdMat); blobs.Label(thresholdMat);
CvBlob selectBlob = null; CvBlob selectBlob = null;
...@@ -1344,6 +1328,8 @@ namespace Acc.Img ...@@ -1344,6 +1328,8 @@ namespace Acc.Img
selectBlob.Contour.Render(imageMat, Scalar.Red); selectBlob.Contour.Render(imageMat, Scalar.Red);
image = BitmapConverter.ToBitmap(imageMat); image = BitmapConverter.ToBitmap(imageMat);
return selectBlob.Area; return selectBlob.Area;
} }
/// <summary> /// <summary>
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!