Commit 8511f266 SK

距离变换找圆法和与料盘中心距离相结合统计数量,

1 个父辈 2671fba1
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="ImageUtil.cs" /> <Compile Include="ImageUtil.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SplitItem.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="FodyWeavers.xml" /> <Content Include="FodyWeavers.xml" />
......
using OpenCvSharp; using AccImage;
using OpenCvSharp;
using OpenCvSharp.Blob; using OpenCvSharp.Blob;
using OpenCvSharp.Extensions; using OpenCvSharp.Extensions;
using System; using System;
...@@ -12,9 +13,6 @@ namespace Acc.Img ...@@ -12,9 +13,6 @@ namespace Acc.Img
{ {
public class ImageUtil public class ImageUtil
{ {
public static bool selectB = false;
public static bool pngB = false;
/// <summary> /// <summary>
/// 读取图片,,支持格式*.raw,*.bmp;*.gif;*.jpg;*.png /// 读取图片,,支持格式*.raw,*.bmp;*.gif;*.jpg;*.png
/// </summary> /// </summary>
...@@ -27,7 +25,6 @@ namespace Acc.Img ...@@ -27,7 +25,6 @@ namespace Acc.Img
{ {
if (imagePath.ToLower().EndsWith(".raw")) if (imagePath.ToLower().EndsWith(".raw"))
{ {
pngB = false;
byte[] src = System.IO.File.ReadAllBytes(imagePath); byte[] src = System.IO.File.ReadAllBytes(imagePath);
int width = 3072; int width = 3072;
int height = 3072; int height = 3072;
...@@ -51,44 +48,22 @@ namespace Acc.Img ...@@ -51,44 +48,22 @@ namespace Acc.Img
System.Runtime.InteropServices.Marshal.Copy(buff, 0, bmpData.Scan0, bmpData.Stride * height); System.Runtime.InteropServices.Marshal.Copy(buff, 0, bmpData.Scan0, bmpData.Stride * height);
bmp.UnlockBits(bmpData); bmp.UnlockBits(bmpData);
//bmp.Save(@"C:\Users\ASA\Desktop\222.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); //bmp.Save(@"C:\Users\ASA\Desktop\222.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
image= bmp; image = bmp;
} }
else else
{ {
pngB = true; image = Image.FromFile(imagePath);
image = Image.FromFile(imagePath);
} }
}catch(Exception) }
catch (Exception)
{ {
} }
return image; return image;
} }
public static Image FindCircle(Image image, int thresh, bool inv)
{
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Cv2.PyrDown(imageMat, imageMat);
Mat threshMat = Threshhold(imageMat, thresh, inv);
//Cv2.GaussianBlur(imageMat, imageMat, new OpenCvSharp.Size(7, 7), 5);
//threshMat = Threshhold(imageMat, thresh, inv);
Mat k1 = Mat.Ones(new OpenCvSharp.Size(21, 21), MatType.CV_8UC1);
Cv2.MorphologyEx(threshMat, threshMat, MorphTypes.Open, k1);
CircleSegment[] circles = Cv2.HoughCircles(threshMat, HoughMethods.Gradient, 1, 5);
foreach(CircleSegment circle in circles)
{
Point2f center = circle.Center;
Cv2.Circle(imageMat, new OpenCvSharp.Point(center.X, center.Y), (int)circle.Radius, Scalar.White);
}
return BitmapConverter.ToBitmap(threshMat);
}
/// <summary> /// <summary>
/// 二值化图像 /// 二值化图像
/// </summary> /// </summary>
...@@ -96,10 +71,10 @@ namespace Acc.Img ...@@ -96,10 +71,10 @@ namespace Acc.Img
/// <param name="thresh">阈值</param> /// <param name="thresh">阈值</param>
/// <param name="inv">true表示元器件为白色,false表示元器件为黑色</param> /// <param name="inv">true表示元器件为白色,false表示元器件为黑色</param>
/// <returns>二值化后的图像</returns> /// <returns>二值化后的图像</returns>
public static Image Threshhold(Image image, int thresh, bool inv=true) public static Image Threshhold(Image image, int thresh)
{ {
Mat imageMat =BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat threshMat = Threshhold(imageMat, thresh, inv); Mat threshMat = Threshhold(imageMat, thresh);
return BitmapConverter.ToBitmap(threshMat); return BitmapConverter.ToBitmap(threshMat);
} }
...@@ -112,10 +87,10 @@ namespace Acc.Img ...@@ -112,10 +87,10 @@ namespace Acc.Img
/// <param name="thresh">二值化阈值</param> /// <param name="thresh">二值化阈值</param>
/// <param name="inv">true表示元器件为白色,false表示元器件为黑色</param> /// <param name="inv">true表示元器件为白色,false表示元器件为黑色</param>
/// <returns>鼠标指向的元器件特征值</returns> /// <returns>鼠标指向的元器件特征值</returns>
public static int GetItemFeature(Image image, int markX = -1, int markY = -1, int thresh = -1, bool inv = true) public static int GetItemFeature(Image image, int markX = -1, int markY = -1, int thresh = -1)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
List<CvBlob> blobList = GetBlobs(imageMat, thresh, inv); List<CvBlob> blobList = GetBlobs(imageMat, thresh);
int blobCount = blobList.Count; int blobCount = blobList.Count;
int selectIndex = blobCount / 2; int selectIndex = blobCount / 2;
if (markX != -1 && markY != -1) if (markX != -1 && markY != -1)
...@@ -136,7 +111,7 @@ namespace Acc.Img ...@@ -136,7 +111,7 @@ namespace Acc.Img
if (markIndex != -1) if (markIndex != -1)
{ {
int area = blobList[markIndex].Area; int area = blobList[markIndex].Area;
area = area * 5/3 - 23; area = area * 5 / 3 - 23;
return area; return area;
} }
} }
...@@ -145,12 +120,12 @@ namespace Acc.Img ...@@ -145,12 +120,12 @@ namespace Acc.Img
public static int GetItemFeatureAuto(Image image, int markX = -1, int markY = -1, int thresh = -1, bool inv = true) public static int GetItemFeatureAuto(Image image, int markX = -1, int markY = -1, int thresh = -1, bool inv = true)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
List<CvBlob> blobList = GetBlobs(imageMat, thresh, inv); List<CvBlob> blobList = GetBlobs(imageMat, thresh);
List<int> sampleList = new List<int>(); List<int> sampleList = new List<int>();
CvBlob srcBlob = new CvBlob(); CvBlob srcBlob = new CvBlob();
srcBlob.Area = -1; srcBlob.Area = -1;
int blobCount = blobList.Count; int blobCount = blobList.Count;
int selectIndex = blobCount / 2+blobCount/16; int selectIndex = blobCount / 2 + blobCount / 16;
for (int i = 0; i < blobList.Count; i++) for (int i = 0; i < blobList.Count; i++)
{ {
if (srcBlob.Area == -1) if (srcBlob.Area == -1)
...@@ -179,7 +154,7 @@ namespace Acc.Img ...@@ -179,7 +154,7 @@ namespace Acc.Img
sampleList.Add(blobList[i].Area); sampleList.Add(blobList[i].Area);
} }
} }
if (sampleList.Count == blobList.Count-1 || i == blobList.Count-1) if (sampleList.Count == blobList.Count - 1 || i == blobList.Count - 1)
{ {
int nums = 0; int nums = 0;
for (int j = 0; j < sampleList.Count; j++) for (int j = 0; j < sampleList.Count; j++)
...@@ -192,7 +167,7 @@ namespace Acc.Img ...@@ -192,7 +167,7 @@ namespace Acc.Img
//int sss = (int)Math.Round(areaI); //int sss = (int)Math.Round(areaI);
return areaI; return areaI;
} }
} }
//if (markX != -1 && markY != -1) //if (markX != -1 && markY != -1)
...@@ -228,30 +203,21 @@ namespace Acc.Img ...@@ -228,30 +203,21 @@ namespace Acc.Img
/// <param name="thresh"></param> /// <param name="thresh"></param>
/// <param name="inv"></param> /// <param name="inv"></param>
/// <returns></returns> /// <returns></returns>
public static int CountItems(ref Image image, int itemFeature, int thresh = -1, bool inv = true) public static int CountItems(ref Image image, int itemArea)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR);
Mat grayMat = BitmapConverter.ToMat(new Bitmap(image)); Mat grayMat = BitmapConverter.ToMat(new Bitmap(image));
Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGBA2RGB); Cv2.CvtColor(grayMat, grayMat, ColorConversionCodes.RGB2GRAY);
if (pngB) CvBlobs blobs = AutoThreshBlobs(ref grayMat, itemArea);
{ int totalCount = findCircles(ref imageMat, grayMat, blobs, itemArea);
Cv2.Threshold(imageMat, imageMat, 70, 255, ThresholdTypes.Binary);
} //int totalCount = CountBlobs(blobs, itemArea, ref imageMat);
else
{
Cv2.Threshold(imageMat, imageMat, 0, 255, ThresholdTypes.Binary);
}
List<CvBlob> blobList = GetBlobs(imageMat, thresh, inv);
int itemArea = (itemFeature + 23) * 3 /5;
if(itemArea <= 0)
{
itemArea = 3;
}
int totalCount = CountBlobs(blobList, itemArea, ref imageMat);
image = BitmapConverter.ToBitmap(imageMat); image = BitmapConverter.ToBitmap(imageMat);
return totalCount; return totalCount;
} }
private static void FindCours(Mat srcMat, Mat threshMat) private static void FindCours(Mat srcMat, Mat threshMat)
{ {
Mat[] contours = null; Mat[] contours = null;
...@@ -322,7 +288,7 @@ namespace Acc.Img ...@@ -322,7 +288,7 @@ namespace Acc.Img
{ {
labels[i] = "1"; labels[i] = "1";
labelCount = labelCount + 1; labelCount = labelCount + 1;
if (anotherBlob.MinX < minX || minX == 0) if (anotherBlob.MinX < minX || minX == 0)
{ {
minX = anotherBlob.MinX; minX = anotherBlob.MinX;
} }
...@@ -334,7 +300,7 @@ namespace Acc.Img ...@@ -334,7 +300,7 @@ namespace Acc.Img
{ {
maxX = anotherBlob.MaxX; maxX = anotherBlob.MaxX;
} }
if (anotherBlob.MaxY> maxY) if (anotherBlob.MaxY > maxY)
{ {
maxY = anotherBlob.MaxY; maxY = anotherBlob.MaxY;
} }
...@@ -372,26 +338,27 @@ namespace Acc.Img ...@@ -372,26 +338,27 @@ namespace Acc.Img
} while (upY > minY); } while (upY > minY);
} }
} }
private static double GetLabelStep(List<CvBlob> blobList, int avgArea, out CvBlob markBlob) private static double GetLabelStep(List<CvBlob> blobList, int avgArea, out CvBlob markBlob)
{ {
int leastNeighbourBlobCount = 15; int leastNeighbourBlobCount = 15;
int selectIndex = blobList.Count / 2; int selectIndex = blobList.Count / 2;
markBlob = blobList[selectIndex]; markBlob = blobList[selectIndex];
for(int i = selectIndex; i< blobList.Count; i ++) for (int i = selectIndex; i < blobList.Count; i++)
{ {
CvBlob blob = blobList[i]; CvBlob blob = blobList[i];
int blobArea = markBlob.Area; int blobArea = markBlob.Area;
if(BlobHasItem(avgArea,blob) == 1) if (BlobHasItem(avgArea, blob) == 1)
// if(blobArea > 0.9 * avgArea && blobArea < 1.1 * avgArea) // if(blobArea > 0.9 * avgArea && blobArea < 1.1 * avgArea)
{ {
//面积与给定的面积差不多,以其为中心,周围至少要有15个Blob //面积与给定的面积差不多,以其为中心,周围至少要有15个Blob
int neighbourCount = 0; int neighbourCount = 0;
int blobRectSize = (blob.MaxX-blob.MinX) < (blob.MaxY - blob.MinY) ? (blob.MaxX - blob.MinX) : (blob.MaxY - blob.MinY); int blobRectSize = (blob.MaxX - blob.MinX) < (blob.MaxY - blob.MinY) ? (blob.MaxX - blob.MinX) : (blob.MaxY - blob.MinY);
double radius = blobRectSize; double radius = blobRectSize;
while (neighbourCount != blobList.Count) while (neighbourCount != blobList.Count)
{ {
neighbourCount = blobList.Count(b => { neighbourCount = blobList.Count(b =>
{
if (BlobHasItem(avgArea, b) >= 1) if (BlobHasItem(avgArea, b) >= 1)
{ {
double distance = blob.Centroid.DistanceTo(b.Centroid); double distance = blob.Centroid.DistanceTo(b.Centroid);
...@@ -414,100 +381,100 @@ namespace Acc.Img ...@@ -414,100 +381,100 @@ namespace Acc.Img
} }
return Math.Sqrt(avgArea); return Math.Sqrt(avgArea);
} }
/// <summary>
/// 获取Blob个数
/// </summary> private static CvBlobs AutoThreshBlobs(ref Mat imageMat, int blobArea)
/// <param name="blobList"></param>
/// <param name="avgArea"></param>
/// <param name="srcMat"></param>
/// <returns></returns>
private static int CountBlobs(List<CvBlob> blobList, int avgArea, ref Mat srcMat)
{ {
//List<CvBlob> filterBlobList = blobList.Where(b => b.Area > 0.3 * avgArea).ToList(); Mat[] mats = new Mat[] { imageMat };//一张图片,初始化为panda
List<CvBlob> filterBlobList = blobList.Where(b => b.Area > 0).ToList(); Mat hist = new Mat();//用来接收直方图
if (blobList.Count == 0) int[] channels = new int[] { 0 };//一个通道,初始化为通道0
int[] histsize = new int[] { 256 };//一个通道,初始化为256箱子
Rangef[] range = new Rangef[1];//一个通道,值范围
range[0].Start = 0.0F;//从0开始(含)
range[0].End = 256.0F;//到256结束(不含)
Mat mask = new Mat();//不做掩码
Cv2.CalcHist(mats, channels, mask, hist, 1, histsize, range);//计算灰度图,dim为1 1维
double total = 0;
for (int i = 0; i < 256; i++)//灰度值总数量
{ {
return 0; total = total + hist.Get<double>(i);
} }
//CvBlob markBlob = null;
//double labelStep = GetLabelStep(blobList, avgArea, out markBlob);
//string[] labels = new string[filterBlobList.Count];
//double markBlobX = markBlob.Centroid.X;
//double markBlobY = markBlob.Centroid.Y;
//LabelBlobsInCircle(ref labels, filterBlobList, markBlobX, markBlobY, labelStep);
//int totalCount = 0;
//for (int i = 0; i < labels.Length; i++)
//{
// if (labels[i] != null)
// {
// CvBlob blob = filterBlobList[i];
// Scalar color = Scalar.Red;
// int count = BlobHasItem(avgArea, blob);
// if (count > 0)
// {
// if (count == 1)
// {
// color = Scalar.Green;
// }
// else if (count == 2)
// {
// color = Scalar.Blue;
// //Cv2.PutText(srcMat, count + "", blob.Centroid, HersheyFonts.HersheySimplex, 0.5, color);
// }
// else if (count >= 3)
// {
// color = Scalar.Red;
// Point2d center = blob.Centroid;
// Cv2.PutText(srcMat, count + "", new OpenCvSharp.Point(center.X, center.Y), HersheyFonts.HersheySimplex, 0.5, color);
// }
// totalCount = totalCount + count;
// blob.Contour.Render(srcMat, color);
// }
// }
//}
int totalCount = 0; double percent = 0;
foreach (CvBlob blob in filterBlobList) int startIndex = -1;
int endIndex = -1;
for (int i = 0; i < 256; i++)//直方图
{ {
Scalar color = Scalar.Red; double len = hist.Get<double>(i);
if (blob.MaxX - blob.MinX > 450 && blob.MaxY - blob.MinY > 450) continue; if(len > 100)
int count = BlobHasItem(avgArea, blob); {//灰度值的像素数小于100的忽略
if (count > 0) percent = percent + len / total;
{ if (startIndex == -1)
if (count == 1)
{
color = Scalar.Green;
}
else if (count == 2)
{ {
color = Scalar.Blue; startIndex = i;
//Cv2.PutText(srcMat, count + "", blob.Centroid, HersheyFonts.HersheySimplex, 0.5, color);
} }
else if (count >= 3) //近似的认为元器件的灰度值 数量占总数的百分比小于10%
if (percent > 0.1)
{ {
color = Scalar.Red; endIndex = i - 1;
Point2d center = blob.Centroid; break;
Cv2.PutText(srcMat, count + "", new OpenCvSharp.Point(center.X, center.Y), HersheyFonts.HersheySimplex, 0.5, color);
} }
totalCount = totalCount + count;
blob.Contour.Render(srcMat, color);
} }
} }
string countText = "Count: " + totalCount;
int baseLine = 0;
OpenCvSharp.Size textSize = Cv2.GetTextSize(countText, HersheyFonts.HersheySimplex, 1, 1, out baseLine);
Cv2.PutText(srcMat, countText, new OpenCvSharp.Point(srcMat.Width / 2 - textSize.Width / 2, srcMat.Height / 2 - textSize.Height / 2), HersheyFonts.HersheySimplex, 1, Scalar.Blue);
//Cv2.Circle(srcMat, markBlob.Centroid, (int)labelStep, Scalar.Red, 2); int avgIndex = (startIndex + endIndex) / 2;
return totalCount; Mat threshMat = new Mat();
Cv2.Threshold(imageMat, threshMat, avgIndex, 255, ThresholdTypes.BinaryInv);
CvBlobs resultBlobs = new CvBlobs();
resultBlobs.Label(threshMat);
List<CvBlob> autoBlobList = resultBlobs.Values.Where(b => b.Area > blobArea).ToList();
int blobCount = resultBlobs.Count();
int threshIndex = avgIndex;
double theArea = blobArea * 0.8;
if (theArea < 1) theArea = 1;
while (true)
{
//阈值向下走,找满足条件Blob数量最多的
threshIndex = threshIndex - 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
if (blobList.Count > blobCount)
{
resultBlobs = blobs;
blobCount = blobList.Count;
}
else
{
break;
}
}
threshIndex = avgIndex;
while (true)
{
//阈值向上走,找满足条件Blob数量最多的
threshIndex = threshIndex + 1;
Cv2.Threshold(imageMat, threshMat, threshIndex, 255, ThresholdTypes.BinaryInv);
CvBlobs blobs = new CvBlobs();
blobs.Label(threshMat);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > theArea).ToList();
if (blobList.Count > blobCount)
{
resultBlobs = blobs;
blobCount = blobList.Count;
}
else
{
break;
}
}
imageMat = threshMat;
Console.WriteLine(threshIndex + "==== Blob: " + blobCount + " Area:" + theArea);
return resultBlobs;
} }
/// <summary> /// <summary>
/// 二值化图像 /// 二值化图像
/// </summary> /// </summary>
...@@ -515,83 +482,24 @@ namespace Acc.Img ...@@ -515,83 +482,24 @@ namespace Acc.Img
/// <param name="thresh"></param> /// <param name="thresh"></param>
/// <param name="inv"></param> /// <param name="inv"></param>
/// <returns></returns> /// <returns></returns>
private static Mat Threshhold(Mat imageMat, int thresh = -1, bool inv = false) private static Mat Threshhold(Mat imageMat, int thresh = -1)
{ {
Mat dst = new Mat(); Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY); Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
//if (selectB)
//{
// //全局二值化
// Cv2.Threshold(dst, dst, 30, 255, ThresholdTypes.Binary);
//}
//else
//{
// //全局二值化
// Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Binary);
//}
//if (selectB)
//{
// if (thresh == -1)
// {
// //自动局部二值化
// Binarizer.Sauvola(dst, dst, 21, 0.2, 32);
// }
// else
// {
// //全局二值化
// if (pngB)
// {
// Cv2.Threshold(dst, dst, 70, 255, ThresholdTypes.Binary);
// }
// else
// {
// Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Binary);
// }
// }
// if (inv)
// {
// if (pngB)
// {
// Cv2.Threshold(dst, dst, 70, 150, ThresholdTypes.BinaryInv);
// }
// else
// {
// Cv2.Threshold(dst, dst, 0, 150, ThresholdTypes.BinaryInv);
// }
// }
//}
//else
//{
// if (pngB)
// {
// Cv2.Threshold(dst, dst, 70, 255, ThresholdTypes.Binary);
// Cv2.Threshold(dst, dst, 0, 150, ThresholdTypes.BinaryInv);
// }
// else
// {
// Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Binary);
// Cv2.Threshold(dst, dst, 0, 150, ThresholdTypes.BinaryInv);
// }
//}
if (thresh == -1) if (thresh == -1)
{ {
//全局自动二值 化
Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.BinaryInv);
//自动局部二值化 //自动局部二值化
Binarizer.Sauvola(dst, dst, 21, 0.2, 32); //Binarizer.Sauvola(dst, dst, 221, 0.02, 232);
//Cv2.AdaptiveThreshold(dst, dst, 255, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 5, 0);
} }
else else
{ {
//全局二值化 //二值化
Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu); Cv2.Threshold(dst, dst, thresh, 255, ThresholdTypes.BinaryInv);
}
if (inv)
{
Cv2.Threshold(dst, dst, 0, thresh, ThresholdTypes.BinaryInv | ThresholdTypes.Otsu);
} }
return dst; return dst;
} }
/// <summary> /// <summary>
...@@ -601,19 +509,16 @@ namespace Acc.Img ...@@ -601,19 +509,16 @@ namespace Acc.Img
/// <param name="thresh"></param> /// <param name="thresh"></param>
/// <param name="inv"></param> /// <param name="inv"></param>
/// <returns></returns> /// <returns></returns>
private static List<CvBlob> GetBlobs(Mat imageMat, int thresh = -1, bool inv = false) private static List<CvBlob> GetBlobs(Mat imageMat, int thresh = -1)
{ {
Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR); Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGBA2BGR);
//Cv2.CvtColor(imageMat, imageMat, ColorConversionCodes.RGB2GRAY); Mat dst = Threshhold(imageMat, thresh);
Mat dst = Threshhold(imageMat, thresh, inv);
Mat k1 = Mat.Ones(new OpenCvSharp.Size(1, 1), MatType.CV_8UC1);
Cv2.MorphologyEx(dst, dst, MorphTypes.Open, k1);
CvBlobs blobs = new CvBlobs(); CvBlobs blobs = new CvBlobs();
blobs.Label(dst); blobs.Label(dst);
List<CvBlob> blobList = blobs.Values.Where(b => b.Area > 0).ToList(); List<CvBlob> blobList = blobs.Values.Where(b => b.Area > 0).ToList();
return blobList; return blobList;
} }
/// <summary> /// <summary>
/// 给定Blob包含几个元器件 /// 给定Blob包含几个元器件
...@@ -631,7 +536,7 @@ namespace Acc.Img ...@@ -631,7 +536,7 @@ namespace Acc.Img
} }
if (blobArea < minArea) if (blobArea < minArea)
{ {
return 1; return 0;
} }
//if (blobArea >= 0.5 * averageArea && blobArea <= 1.5 * averageArea) //if (blobArea >= 0.5 * averageArea && blobArea <= 1.5 * averageArea)
//{ //{
...@@ -645,8 +550,8 @@ namespace Acc.Img ...@@ -645,8 +550,8 @@ namespace Acc.Img
//{ //{
// return 3; // return 3;
//} //}
int count = (int)((blobArea+1.5 * averageArea) / (1.5 * averageArea)); int count = (int)((blobArea + 1.5 * averageArea) / (1.5 * averageArea));
if(count == 0) if (count == 0)
{ {
count = 1; count = 1;
} }
...@@ -665,7 +570,7 @@ namespace Acc.Img ...@@ -665,7 +570,7 @@ namespace Acc.Img
private static Bitmap[] ReadRaw(string imagePath) private static Bitmap[] ReadRaw(string imagePath)
{ {
byte[] buff = System.IO.File.ReadAllBytes(imagePath); byte[] buff = System.IO.File.ReadAllBytes(imagePath);
if (buff == null || buff.Length == 0) if (buff == null || buff.Length == 0)
{ {
...@@ -695,7 +600,7 @@ namespace Acc.Img ...@@ -695,7 +600,7 @@ namespace Acc.Img
byte filterByte = buff[i * 2 + 1]; byte filterByte = buff[i * 2 + 1];
if (needRevertLayer) if (needRevertLayer)
{ {
currentByte = (byte)(currentByte * 3); currentByte = (byte)(currentByte * 3);
filterByte = (byte)(filterByte * 3); filterByte = (byte)(filterByte * 3);
} }
buffer_src[i] = currentByte; buffer_src[i] = currentByte;
...@@ -713,11 +618,11 @@ namespace Acc.Img ...@@ -713,11 +618,11 @@ namespace Acc.Img
//翻转图层 //翻转图层
if (needRevertLayer) if (needRevertLayer)
{ {
return new Bitmap[] { filter_bitmap, src_bitmap}; return new Bitmap[] { filter_bitmap, src_bitmap };
} }
else else
{ {
return new Bitmap[] { src_bitmap, filter_bitmap}; return new Bitmap[] { src_bitmap, filter_bitmap };
} }
} }
/// <summary> /// <summary>
...@@ -751,11 +656,9 @@ namespace Acc.Img ...@@ -751,11 +656,9 @@ namespace Acc.Img
return bmp; return bmp;
} }
private static List<OpenCvSharp.Point> findContourPoints(CvBlob blob) private static List<OpenCvSharp.Point> toContourPoints(CvContourChainCode contour)
{ {
CvContourChainCode contour = blob.Contour;
List<OpenCvSharp.Point> contourPoints = new List<OpenCvSharp.Point>(); List<OpenCvSharp.Point> contourPoints = new List<OpenCvSharp.Point>();
contourPoints.Add(contour.StartingPoint); contourPoints.Add(contour.StartingPoint);
int x = contour.StartingPoint.X; int x = contour.StartingPoint.X;
int y = contour.StartingPoint.Y; int y = contour.StartingPoint.Y;
...@@ -768,7 +671,7 @@ namespace Acc.Img ...@@ -768,7 +671,7 @@ namespace Acc.Img
return contourPoints; return contourPoints;
} }
private static CvBlob findMarkBlob(List<CvBlob> blobList, int markX = -1, int markY = -1, int thresh = -1, bool inv = true) private static CvBlob findMarkBlob(List<CvBlob> blobList, int markX = -1, int markY = -1, int thresh = -1, bool inv = true)
{ {
int blobCount = blobList.Count; int blobCount = blobList.Count;
int selectIndex = blobCount / 2; int selectIndex = blobCount / 2;
...@@ -795,144 +698,354 @@ namespace Acc.Img ...@@ -795,144 +698,354 @@ namespace Acc.Img
} }
return null; return null;
} }
public static Image Mark(Image image, int markX = -1, int markY = -1, int thresh = -1, bool inv = true)
/// <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 SplitItem findCircleInBlob(ref double[,] matDistanceArr, CvBlobs blobs, CvBlob blob, Point2d reelCenter, double oneBlobWidth= -1, double oneBlobRadius = -1)
{ {
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image)); SplitItem item = new SplitItem();
List<CvBlob> blobList = GetBlobs(imageMat, thresh, inv); while (true)
//TODO:查找标记Blob,这里可遍历blobList,对BlobHasItem结果为1的blob进行标记,查找最小的内接半径 {
CvBlob markBlob = findMarkBlob(blobList, markX, markY, thresh, inv); bool hasFind = false;
if(markBlob != null) for (int y = blob.MinY; y < blob.MaxY; y++)
{ {
OpenCvSharp.Point center = new OpenCvSharp.Point() ; for (int x = blob.MinX; x < blob.MaxX; x++)
double r = 0;
findCircle(markBlob, out center, out r);
Cv2.Circle(imageMat, center, (int)r, Scalar.Red);
Console.WriteLine("" + r);
int markArea = markBlob.Area;
int totalCount = 0;
foreach(CvBlob blob in blobList)
{
int count = BlobHasItem(markArea, blob);
totalCount = totalCount + count;
if (count == 1)
{//单个Blob
blob.Contour.Render(imageMat, Scalar.Green);
}
else if (count >0 && count < 100)
{ {
//查找对大一点的Blob的内接圆数量,进行标记 double distance = matDistanceArr[x, y];
Stopwatch sw = new Stopwatch(); if (distance > 0)
sw.Start();
List<OpenCvSharp.Point> centers = markBlobInImage(blob, r);
foreach(OpenCvSharp.Point c in centers)
{ {
Cv2.Circle(imageMat, c, (int)r, Scalar.Red); int label = blobs.GetLabel(x, y);
if (label != blob.Label)
{
//不是当前Blob的像素
matDistanceArr[x, y] = 0;
continue;
}
if (!item.isEnd)
{
double distanceToCircle = item.minDistanceToCircles(x, y, reelCenter);
if (distanceToCircle == 0)
{
matDistanceArr[x, y] = 0;
continue;
}
if (distanceToCircle> 0 && distanceToCircle < distance)
{
distance = distanceToCircle;
matDistanceArr[x, y] = distance;
}
if (distance > item.currentMaxRadius)
{
item.currentMaxRadius = distance;
item.centerX = x;
item.centerY = y;
if (oneBlobRadius != -1 && distance >= oneBlobRadius)
{
item.calOneItem(oneBlobRadius);
hasFind = true;
break;
}
}
}
} }
sw.Stop();
Console.WriteLine("耗时:" + sw.ElapsedMilliseconds + " ms 数量:"+ centers.Count);
} }
if (hasFind)
{
break;
}
}
if (!hasFind)
{
item.calOneItem(oneBlobRadius);
}
if (item.isEnd)
{
break;
} }
} }
return item;
return BitmapConverter.ToBitmap(imageMat);
} }
/// <summary> /// <summary>
/// 查找Blob包含多少个指定半径的圆 /// 查找Blobs包含的元器件数量
/// </summary> /// </summary>
/// <param name="blob"></param> /// <param name="srcMat"></param>
/// <param name="radius">指定半径</param> /// <param name="threshMat"></param>
/// <returns>找到的圆的中心点列表,一个中心点为一个圆</returns> /// <param name="blobs"></param>
private static List<OpenCvSharp.Point> markBlobInImage(CvBlob blob, double radius) /// <param name="avgArea"></param>
/// <returns></returns>
public static int findCircles(ref Mat srcMat, Mat threshMat, CvBlobs blobs, int avgArea)
{ {
List<OpenCvSharp.Point> centers = new List<OpenCvSharp.Point>(); Mat distanceMat = new Mat();
List<OpenCvSharp.Point> contourPoints = findContourPoints(blob); Cv2.DistanceTransform(threshMat, distanceMat, DistanceTypes.L2, DistanceMaskSize.Mask3);
CvContourPolygon polygon = blob.Contour.ConvertToPolygon(); double[,] distanceArr = new double[threshMat.Cols, threshMat.Rows];
//从左向右,从上到下遍历 Console.WriteLine("Start to distance array");
int x = blob.MinX; for (int y = 0; y < threshMat.Rows; y++)
while(x <= blob.MaxX) {
{ for (int x = 0; x < threshMat.Cols; x++)
int y = blob.MinY; {
while (y <= blob.MaxY) distanceArr[x,y] = distanceMat.At<float>(y, x);
{ }
//当前的遍历的点 }
OpenCvSharp.Point currentPoint = new OpenCvSharp.Point(x, y);
double distance = Cv2.PointPolygonTest(contourPoints, currentPoint, true); Dictionary<int, SplitItem> blobCircles = new Dictionary<int, SplitItem>();
//TODO: 内轮廓也需要判断
if(distance >= radius) Console.WriteLine("Start find reel center");
Point2d reelCenter = new Point2d(0,0) ;
//查找中心
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if (count > 10 && reelCenter.X == 0)
{
Point2d center = blob.Centroid;
//中间的圆,查找圆心
if (center.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{ {
//当前点到轮廓的最小距离大于半径时,判断是否与其他圆相交,如果相交,忽略这个点 reelCenter = center;
bool valid = true; srcMat.Line(new OpenCvSharp.Point(center.X-10, center.Y), new OpenCvSharp.Point(center.X+10, center.Y), Scalar.Blue);
foreach (OpenCvSharp.Point c in centers) srcMat.Line(new OpenCvSharp.Point(center.X, center.Y-10), new OpenCvSharp.Point(center.X, center.Y+10), Scalar.Blue);
{ break;
double dis = currentPoint.DistanceTo(c); }
if (dis < 2 * radius) }
{ }
valid = false;
break; Console.WriteLine("Start find reel Max Radius, max Width");
} //最大
} double maxRadius = 0;
if (valid) double maxWidth = 0;
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if (count == 1)
{
if (blob.Rect.Width > maxWidth)
{
maxWidth = blob.Rect.Width;
}
if (blob.Rect.Height > maxWidth)
{
maxWidth = blob.Rect.Height;
}
SplitItem item = findCircleInBlob(ref distanceArr, blobs, blob, reelCenter);
foreach (Circle c in item.circles)
{
if (c.radius > maxRadius || maxRadius == 0)
{ {
//找到一个,从当前点向下偏移一个半径的距离 maxRadius = c.radius;
y = (int)(y + radius);
Console.WriteLine("" + x + ", " + y + " dis=" + distance + " ");
centers.Add(currentPoint);
} }
else //srcMat.Circle(c.x, c.y, (int)c.radius, Scalar.Green);
}
}
}
Console.WriteLine("Start count");
int totalCount = 0;
foreach (CvBlob blob in blobs.Values)
{
int count = BlobHasItem(avgArea, blob);
if(count == 1)
{
//单个元器件
totalCount = totalCount +1;
srcMat.Circle((int)blob.Centroid.X, (int)blob.Centroid.Y, (int)maxRadius/2, Scalar.LightGreen);
}
else if (count > 1)
{
if (count > 20)
{
//中间的圆,去除
if(blob.Centroid.DistanceTo(new Point2d(srcMat.Cols / 2, srcMat.Rows / 2)) < 200)
{ {
//与其他圆相交,忽略,继续下一个点 continue;
y++;
} }
} }
else //多个元器件,查找 所有圆
SplitItem item = findCircleInBlob(ref distanceArr, blobs, blob, reelCenter, maxWidth, maxRadius);
//对所有圆进行分组
List<List<Circle>> groupCircles = item.groupCircles(maxWidth, maxRadius, reelCenter);
Scalar color = Scalar.RandomColor();
blob.Contour.Render(srcMat, color);
foreach (List<Circle> groupCircle in groupCircles)
{ {
//当前点到轮廓的最小距离小于半径,继续下一个点 Circle c = groupCircle[0];
y++; srcMat.Circle(c.x, c.y, (int)c.radius/2, Scalar.Yellow);
totalCount = totalCount + 1;
//Scalar color = Scalar.RandomColor();
//foreach (Circle c in groupCircle)
//{
// srcMat.Circle(c.x, c.y, (int)c.radius, color);
//}
} }
} }
x++;
} }
return centers;
Cv2.PutText(srcMat, totalCount + "", new OpenCvSharp.Point(reelCenter.X-40, reelCenter.Y+30), HersheyFonts.HersheySimplex, 1.0, Scalar.LightGreen);
Console.WriteLine("===========" + totalCount);
return totalCount;
} }
/// <summary> //TODO: 测试距离变换,用后删除
/// 查找Blob最大的内接圆 public static Image DistanceTransform(Image image)
/// </summary>
/// <param name="blob"></param>
/// <param name="centerPoint"></param>
/// <param name="r"></param>
private static void findCircle(CvBlob blob, out OpenCvSharp.Point centerPoint, out double r)
{ {
//TODO: 需要进行修改,找多个,这里只找了一个 Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
List<OpenCvSharp.Point> contourPoints = findContourPoints(blob); Mat gray = new Mat();
OpenCvSharp.Point center = new OpenCvSharp.Point(-1,-1); Cv2.CvtColor(imageMat, gray, ColorConversionCodes.RGB2GRAY);
double ridus = 0; ////开运算
for (int x = blob.MinX; x < blob.MaxX; x++) 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)
{ {
for(int y= blob.MinY; y<blob.MaxY; y++) circle.calOneItem(-1);
}
while (true)
{
for (int y = 0; y < labels.Rows; y++)
{ {
OpenCvSharp.Point currentPoint = new OpenCvSharp.Point(x, y); for (int x = 0; x < labels.Cols; x++)
double minDistance = -1;
foreach (OpenCvSharp.Point p in contourPoints)
{ {
double distance = currentPoint.DistanceTo(p); int label = labels.At<int>(y, x);
if (distance < minDistance || minDistance == -1) if (label == 0) continue;
SplitItem item = new SplitItem();
if (blobCircles.ContainsKey(label))
{ {
minDistance = distance; 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;
}
}
} }
} }
if(minDistance > ridus) }
bool needContinue = false;
foreach (SplitItem circle in blobCircles.Values)
{
circle.calOneItem();
if (!circle.isEnd)
{ {
ridus = minDistance; needContinue = true;
center = currentPoint;
} }
} }
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;
}
/// <summary>
/// 获取单个元器件的特征
/// </summary>
/// <param name="image"></param>
/// <param name="markX"></param>
/// <param name="markY"></param>
/// <returns></returns>
public static int GetFeature(ref Image image, int markX, int markY)
{
Mat imageMat = BitmapConverter.ToMat(new Bitmap(image));
Mat dst = new Mat();
Cv2.CvtColor(imageMat, dst, ColorConversionCodes.RGB2GRAY);
//全局二值化
Cv2.Threshold(dst, dst, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.BinaryInv);
image = BitmapConverter.ToBitmap(dst);
CvBlobs blobs = new CvBlobs();
blobs.Label(dst);
foreach(CvBlob blob in blobs.Values) {
if (blob.Rect.Contains(new OpenCvSharp.Point(markX, markY)))
{
return blob.Area;
}
} }
centerPoint = center; return -1;
r = ridus;
} }
} }
} }
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AccImage
{
public class SplitItem
{
public bool isEnd = false;
public double avgRadius = 0;
public int centerX = 0;
public int centerY = 0;
public double currentMaxRadius = 0;
public List<Circle> circles = new List<Circle>();
/// <summary>
/// 一遍结束后调用
/// </summary>
public void calOneItem(double theFixRadius=-1)
{
//该半径是否有效
bool isValid = false;
if (avgRadius == 0)
{
isValid = true;
}
else
{
//与平均半径差值在10%以内,认为OK
double diff = avgRadius - currentMaxRadius;
if (diff/avgRadius <= 0.2)
{
isValid = true;
}
}
if (isValid)
{
Circle circle = new Circle();
if(theFixRadius != -1 && currentMaxRadius > theFixRadius)
{
currentMaxRadius = theFixRadius;
}
circle.radius = currentMaxRadius;
circle.x = centerX;
circle.y = centerY;
circles.Add(circle);
currentMaxRadius = 0;
centerX = 0;
centerY = 0;
//平均半径
double total = 0;
foreach (Circle c in circles)
{
total = total + c.radius;
}
avgRadius = total / circles.Count;
}
else
{
isEnd = true;
}
}
public List<List<Circle>> groupCircles(double w, double h, Point2d center)
{
foreach(Circle c in circles)
{
c.calDistanceToCenter(center);
}
List<List<Circle>> allGroupCircle = new List<List<Circle>>();
List<int> allreadyGroup = new List<int>();
while (true)
{
List<Circle> groupCircle = new List<Circle>();
Circle labelCircle = null;
for (int i=0;i<circles.Count; i++)
{
if (!allreadyGroup.Contains(i))
{
Circle c = circles[i];
if (labelCircle == null)
{
labelCircle = c;
allreadyGroup.Add(i);
groupCircle.Add(c);
}
else
{
//到圆心的距离差小于H
if (Math.Abs(c.distanceToCenter - labelCircle.distanceToCenter) < h)
{
//两圆心之间的距离+直径小于W认为是同一个元器件
if (c.distanceToCircle(labelCircle) < w)
{
groupCircle.Add(c);
allreadyGroup.Add(i);
}
}
}
}
}
allGroupCircle.Add(groupCircle);
if (allreadyGroup.Count == circles.Count)
{
break;
}
}
return allGroupCircle;
}
/// <summary>
/// 该点是否与其他圆内,或与圆的中心距离在半径内
/// </summary>
/// <param name="px"></param>
/// <param name="py"></param>
/// <returns></returns>
public double minDistanceToCircles(int px, int py, Point2d reelCenter, double oneBlobWidth =-1, double oneBlobRadius = -1)
{
Point2d point = new Point2d(px, py);
double minDistanceToCircle = -1;
foreach (Circle c in circles)
{
Point2d circleCenter = new Point2d(c.x, c.y);
double distanceToCircle = point.DistanceTo(circleCenter);
if (distanceToCircle <= c.radius)
{
return 0;
}
//当前点到料盘中心与圆心到料盘中心的距离在直径内,忽略
//if(oneBlobRadius != -1 && oneBlobWidth != -1)
//{
// double distanceToReelCenter = point.DistanceTo(reelCenter);
// double circleCenterToReelCenter = circleCenter.DistanceTo(reelCenter);
// if (Math.Abs(distanceToReelCenter - circleCenterToReelCenter) < oneBlobRadius)
// {
// if (distanceToCircle < oneBlobWidth)
// {
// return 0;
// }
// }
//}
if (minDistanceToCircle == -1 || distanceToCircle < minDistanceToCircle)
{
minDistanceToCircle = distanceToCircle - c.radius;
}
}
return minDistanceToCircle;
}
};
public class Circle
{
public int x;
public int y;
public double radius;
public double distanceToCenter = 0;
public double distanceToCircle(Circle c)
{
double distance = new Point2d(x, y).DistanceTo(new Point2d(c.x, c.y));
return distance + radius + c.radius;
}
public void calDistanceToCenter(Point2d center)
{
if(center.X > 0 && distanceToCenter <= 0)
{
distanceToCenter = center.DistanceTo(new Point2d(x, y));
}
}
}
}
...@@ -69,7 +69,16 @@ namespace Acc.Demo ...@@ -69,7 +69,16 @@ namespace Acc.Demo
{ {
theshValue = int.Parse(textBoxThesh.Text); theshValue = int.Parse(textBoxThesh.Text);
} }
Image result = ImageUtil.Threshhold(orginalImage, theshValue, false); Image result;
result = ImageUtil.Threshhold(orginalImage, theshValue);
//if (theshValue == -1)
//{
// result = ImageUtil.Threshhold(imageBox.Image, theshValue);
//}
//else
//{
// result = ImageUtil.DistanceTransform(imageBox.Image);
//}
imageBox.Image = result; imageBox.Image = result;
} }
...@@ -105,26 +114,12 @@ namespace Acc.Demo ...@@ -105,26 +114,12 @@ namespace Acc.Demo
private void Count() private void Count()
{ {
ClearStatusBar(); ClearStatusBar();
int theshValue = -1;
if (!checkBoxAutoThresh.Checked)
{
theshValue = int.Parse(textBoxThesh.Text);
}
Task.Factory.StartNew(delegate { Task.Factory.StartNew(delegate {
//Image image = ImageUtil.FindCircle(orginalImage, theshValue, inv);
//imageBox.Image = image;
Stopwatch sw = new Stopwatch(); Stopwatch sw = new Stopwatch();
sw.Start(); sw.Start();
int itemFeature = int.Parse(textBoxFeature.Text); int itemFeature = int.Parse(textBoxFeature.Text);
Image image = orginalImage; Image image = orginalImage;
if (!ImageUtil.selectB) int count = ImageUtil.CountItems(ref image, itemFeature);
{
itemFeature = ImageUtil.GetItemFeatureAuto(image, markX, markY, theshValue);
}
ImageUtil.selectB = false;
int count = ImageUtil.CountItems(ref image, itemFeature, theshValue);
sw.Stop(); sw.Stop();
labelTime.Text = "耗时:" + sw.ElapsedMilliseconds + " ms"; labelTime.Text = "耗时:" + sw.ElapsedMilliseconds + " ms";
labelCount.Text = "数量:" + count; labelCount.Text = "数量:" + count;
...@@ -152,14 +147,23 @@ namespace Acc.Demo ...@@ -152,14 +147,23 @@ namespace Acc.Demo
private void 元件特征ToolStripMenuItem_Click(object sender, EventArgs e) private void 元件特征ToolStripMenuItem_Click(object sender, EventArgs e)
{ {
ClearStatusBar(); ClearStatusBar();
int theshValue = -1; Image image = orginalImage;
if (!checkBoxAutoThresh.Checked) int feature = ImageUtil.GetFeature(ref image, markX, markY);
{ textBoxFeature.Text = feature.ToString();
theshValue = int.Parse(textBoxThesh.Text);
}
ImageUtil.selectB = true;
Image image = ImageUtil.Mark(orginalImage, markX, markY, theshValue);
imageBox.Image = image; imageBox.Image = image;
//int theshValue = -1;
//if (!checkBoxAutoThresh.Checked)
//{
// theshValue = int.Parse(textBoxThesh.Text);
//}
//Stopwatch sw = new Stopwatch();
//sw.Start();
//Image image = ImageUtil.Mark(orginalImage, markX, markY, theshValue);
//imageBox.Image = image;
//sw.Stop();
//Console.WriteLine("总耗时:" + sw.ElapsedMilliseconds + " ms");
} }
private void 保存当前图片ToolStripMenuItem_Click(object sender, EventArgs e) private void 保存当前图片ToolStripMenuItem_Click(object sender, EventArgs e)
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
// //
this.元件特征ToolStripMenuItem.Name = "元件特征ToolStripMenuItem"; this.元件特征ToolStripMenuItem.Name = "元件特征ToolStripMenuItem";
this.元件特征ToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.元件特征ToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
this.元件特征ToolStripMenuItem.Text = "标记记数"; this.元件特征ToolStripMenuItem.Text = "元件特征";
this.元件特征ToolStripMenuItem.Click += new System.EventHandler(this.元件特征ToolStripMenuItem_Click); this.元件特征ToolStripMenuItem.Click += new System.EventHandler(this.元件特征ToolStripMenuItem_Click);
// //
// 计数ToolStripMenuItem // 计数ToolStripMenuItem
......
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!