OpenCV学习笔记16 OpenCV图像处理模块ImgProc Module. Image Processing(九)
发布时间
阅读量:
阅读量
3.24 图像矩 - Image Moments
使用 moments 函数计算图像所有的矩(最高到3阶)。
使用 contourArea 函数计算轮廓面积。
使用 arcLength 函数计算轮廓或曲线长度。
/** @thresh_callback 函数 */
void thresh_callback(int, void* )
{
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
/// 使用Canndy检测边缘
Canny( src_gray, canny_output, thresh, thresh*2, 3 );
/// 找到轮廓
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
/// 计算矩
vector<Moments> mu(contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mu[i] = moments( contours[i], false ); }
/// 计算中心矩:
vector<Point2f> mc( contours.size() );
for( int i = 0; i < contours.size(); i++ )
{ mc[i] = Point2f( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }
/// 绘制轮廓
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
for( int i = 0; i< contours.size(); i++ )
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
/// 显示到窗口中
namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
imshow( "Contours", drawing );
/// 通过m00计算轮廓面积并且和OpenCV函数比较
printf("\t Info: Area and Contour Length \n");
for( int i = 0; i< contours.size(); i++ )
{
printf(" * Contour[%d] - Area (M_00) = %.2f - Area OpenCV: %.2f - Length: %.2f \n", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
circle( drawing, mc[i], 4, color, -1, 8, 0 );
}
}
moments 函数参数说明:
contour[i]_ 是一种用于表示图形形状的数据结构:它存储了栅格图像(单色、8位或浮点型 2维数组)或二维点(Point或Point2f类型)的数组(大小为1×N 或 N×1)。
false 是一个二值图像标志位变量,在其值为true时表示该图像的所有非零像素被标记为1。
contourArea 函数参数说明:
contours[i] :2维点数组,存储在 vector 或 Mat 中。
arcLength 函数参数说明:
contours[i] :2维点数组,存储在 vector 或 Mat 中。
true :曲线是否封闭的标志。
3.25 点多边形测试
使用 pointPolygonTest 函数进行点是否在轮廓中的测试。
/// 创建一个图形
const int r = 100;
Mat src = Mat::zeros( Size( 4*r, 4*r ), CV_8UC1 );
/// 绘制一系列点创建一个轮廓:
vector<Point2f> vert(6);
vert[0] = Point( 1.5*r, 1.34*r );
vert[1] = Point( 1*r, 2*r );
vert[2] = Point( 1.5*r, 2.866*r );
vert[3] = Point( 2.5*r, 2.866*r );
vert[4] = Point( 3*r, 2*r );
vert[5] = Point( 2.5*r, 1.34*r );
/// 在src内部绘制
for( int j = 0; j < 6; j++ )
{ line( src, vert[j], vert[(j+1)%6], Scalar( 255 ), 3, 8 ); }
/// 得到轮廓
vector<vector<Point> > contours; vector<Vec4i> hierarchy;
Mat src_copy = src.clone();
findContours( src_copy, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
/// 计算到轮廓的距离
Mat raw_dist( src.size(), CV_32FC1 );
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{ raw_dist.at<float>(j,i) = pointPolygonTest( contours[0], Point2f(i,j), true ); }
}
double minVal; double maxVal;
minMaxLoc( raw_dist, &minVal, &maxVal, 0, 0, Mat() );
minVal = abs(minVal); maxVal = abs(maxVal);
/// 图形化的显示距离
Mat drawing = Mat::zeros( src.size(), CV_8UC3 );
for( int j = 0; j < src.rows; j++ )
{ for( int i = 0; i < src.cols; i++ )
{
if( raw_dist.at<float>(j,i) < 0 )
{ drawing.at<Vec3b>(j,i)[0] = 255 - (int) abs(raw_dist.at<float>(j,i))*255/minVal; }
else if( raw_dist.at<float>(j,i) > 0 )
{ drawing.at<Vec3b>(j,i)[2] = 255 - (int) raw_dist.at<float>(j,i)*255/maxVal; }
else
{ drawing.at<Vec3b>(j,i)[0] = 255; drawing.at<Vec3b>(j,i)[1] = 255; drawing.at<Vec3b>(j,i)[2] = 255; }
}
}
pointPolygonTest 函数参数说明:
contours[0] :输入轮廓。
Point2f(i,j) :测试点。
true :标记位用于距离测量。当设置为true时,则函数计算并返回该点至轮廓的有符号最近距离(正值表示外部区域、负值表示内部区域)。当设置为false时,则仅判断该点是否位于轮廓之内。
全部评论 (0)
还没有任何评论哟~
