我需要检测这些线的宽度:
这些线是平行的并且有一些噪音。
目前,我所做的是:
1.使用细化处理中心(ZhangSuen)
ZhanSuenThinning(binImage, thin);
2.计算距离变换
cv::distanceTransform(binImage, distImg, CV_DIST_L2, CV_DIST_MASK_5);
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 ++;
}
4.最后,获取实际宽度
width = halfWidth / count * 2;
结果,并不是很好,在1-2像素左右是错误的。在更大的图像上,结果更糟,有什么建议吗?
答案 0 :(得分:9)
您可以采用条形码阅读器算法,这是更快的方法。
扫描水平和垂直线条。 让X表示与黑线的水平交点的长度,Y表示垂直交点的长度(如果有一些噪音,可以计算几个X和Y的中值)。
X * Y / 2 = area
X²+Y² = hypotenuse²
hypotenuse * width / 2 = area
所以:width = 2 * area / hypotenuse
编辑:您也可以使用PCA轻松找到角度。
答案 1 :(得分:4)
你需要的是为你的图像中的每个轮廓找到RotatedRect,这里是OpenCV tutorial如何做到这一点。然后从旋转的矩形中获取“大小”的值,在这里您将获得轮廓的高度和宽度,高度和宽度可以互换以用于轮廓的不同对齐。在上图中,高度变为宽度,宽度变为高度。
Contour-->RotatedRect
|
'--> Size2f size
|
|-->width
'-->height
找到轮廓后再做
RotatedRect minRect = minAreaRect( Mat(contours[i]) );
Size2f contourSize=minRect.size // width and height of the rectangle
每个轮廓的旋转矩形
这是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);
答案 2 :(得分:2)
尽管可以使用连通分量算法来查找线条,但它不会像样条拟合那样找到“真实”边缘。
答案 3 :(得分:1)
一个简单明了的建议:
计算黑色像素的总数。
检测每条线的长度。 (可能使用CVHoughLinesP,或者只是每条细化线周围的边界框的对角线)
将黑色像素数除以所有线长的总和,这样就可以得到平均线宽。
我不确定这是否比现有方法更准确。每行的不规则末端部分可能会抛出它。
您可以尝试的一件事可以提高该案例的准确性:
答案 4 :(得分:0)
您所显示的图像有噪音/模糊,因此黑色像素的数量可能无法反映线条属性;例如,黑色像素可以部分归因于椒盐噪声。你可以通过形态侵蚀摆脱它,但这也会影响你的线条。
更好的方法是提取连通分量,删除可能来自噪声或小斑点的小分量,然后计算像素数并将其除以行数。这种方法还可以帮助您分析图像中对象的形状,并除去噪声或线条以外的任何伪像。
当您有一些接近线条边框的灰色像素时,不同的真实字词情况。您可以使用阈值来丢弃它们,也可以使用一些权重<1来计算它们。这将补偿图像中的模糊。顺便说一下,图像的旋转可能会增加模糊,因为它通常通过插值和平滑来完成。