aze*_*r89 6 opencv image-processing computer-vision
我需要检测这些线的宽度:

这些线是平行的并且有一些噪音.
目前,我所做的是:
1.使用减薄找到中心(张颂)
ZhanSuenThinning(binImage, thin);
Run Code Online (Sandbox Code Playgroud)
2.计算距离变换
cv::distanceTransform(binImage, distImg, CV_DIST_L2, CV_DIST_MASK_5);
Run Code Online (Sandbox Code Playgroud)
3.累积中心周围的一半距离
double halfWidth = 0.0;
int count = 0;
for(int a = 0; a < thinImg.cols; a++)
for(int b = 0; b < thinImg.rows; b++)
if(thinImg.ptr<uchar>(b, a)[0] > 0)
{
halfWidth += distImg.ptr<float>(b, a)[0];
count ++;
}
Run Code Online (Sandbox Code Playgroud)
4.最后,获得实际宽度
width = halfWidth / count * 2;
Run Code Online (Sandbox Code Playgroud)
结果,不太好,在1-2像素左右是错误的.在更大的图像上,结果更糟,有什么建议吗?
小智 10
您可以调整条形码阅读器算法,这是更快的方法.

扫描水平和垂直线条.让X表示与黑线的水平交点的长度,Y表示垂直交点的长度(如果有一些噪音,可以计算几个X和Y的中值).
X * Y / 2 = area
X²+Y² = hypotenuse²
hypotenuse * width / 2 = area
Run Code Online (Sandbox Code Playgroud)
所以:width = 2*area/hypotenuse
编辑:您也可以使用PCA轻松找到角度.
您需要为图像中的每个轮廓找到RotatedRect,这是OpenCV教程的操作方法。然后,只需从旋转的矩形中获取“大小”的值,即可获得轮廓的高度和宽度,高度和宽度可能会因轮廓的不同对齐方式而互换。在上图中,高度变为宽度,宽度变为高度。
Contour-->RotatedRect
|
'--> Size2f size
|
|-->width
'-->height
Run Code Online (Sandbox Code Playgroud)
找到轮廓后就做
RotatedRect minRect = minAreaRect( Mat(contours[i]) );
Size2f contourSize=minRect.size // width and height of the rectangle
Run Code Online (Sandbox Code Playgroud)
每个轮廓的旋转矩形

这是C ++代码
Mat src=imread("line.png",1);
Mat thr,gray;
blur(src,src,Size(3,3));
cvtColor(src,gray,CV_BGR2GRAY);
Canny(gray,thr,50, 190, 3, false );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( thr.clone(),contours,hierarchy,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE,Point(0,0));
vector<RotatedRect> minRect( contours.size() );
for( int i = 0; i < contours.size(); i++ )
minRect[i] = minAreaRect( Mat(contours[i]) );
for( int i = 0; i< contours.size(); i++ )
{
cout<<" Size ="<<minRect[i].size<<endl; //The width may interchange according to contour alignment
Size2f s=minRect[i].size;
// rotated rectangle
Point2f rect_points[4]; minRect[i].points( rect_points );
for( int j = 0; j < 4; j++ )
line( src, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 1, 8 );
}
imshow("src",src);
imshow("Canny",thr);
Run Code Online (Sandbox Code Playgroud)
一个快速而简单的建议:
计算黑色像素的总数。
检测每条线的长度。(也许使用 CVHoughLinesP,或者只是每条细线周围的边界框的对角线)
将黑色像素的数量除以所有线条长度的总和,即可得出平均线条宽度。
我不确定这是否比您现有的方法更准确。每条线的不规则末端部分可能会使其脱落。
您可以尝试一件事来提高这种情况的准确性:
| 归档时间: |
|
| 查看次数: |
5932 次 |
| 最近记录: |