天天看点

OpenCV 求特征区域的多种特征值

一:问题提出

   使用特征值做特征分析是图像处理中常用的手段,比如 提取面积、长度、圆度、偏心度、偏斜角度等等,在Halcon中一般会用相关的特征获取方法,但在OpenCV中有的并没有相关算法,需要在学习过程中 不断总结。

在如下代码中用到了一些特征提取的方式,个人认为比较不错记录如下:

#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
Mat src; Mat src_gray;
int thresh = 30;
int max_thresh = 255;
RNG rng(12345);
int main(){
	src = imread( "opencv-logo.png" ,CV_LOAD_IMAGE_COLOR );
	cvtColor( src, src_gray, CV_BGR2GRAY );//灰度化
	GaussianBlur( src, src, Size(3,3), 0.1, 0, BORDER_DEFAULT );
	blur( src_gray, src_gray, Size(3,3) ); //滤波
	namedWindow( "image", CV_WINDOW_AUTOSIZE );
	imshow( "image", src );
	moveWindow("image",20,20);
	//定义Canny边缘检测图像
	Mat canny_output;
	vector<vector<Point> > contours;
	vector<Vec4i> hierarchy;
	//利用canny算法检测边缘
	Canny( src_gray, canny_output, thresh, thresh*3, 3 );
	namedWindow( "canny", CV_WINDOW_AUTOSIZE );
	imshow( "canny", canny_output );
	moveWindow("canny",550,20);
	//查找轮廓
	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] = Point2d( mu[i].m10/mu[i].m00 , mu[i].m01/mu[i].m00 ); }

	//画轮廓及其质心并显示
	Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );
	printf("\t\t 几何特性\n");
	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 );		
		rectangle(drawing, boundingRect(contours.at(i)), cvScalar(0,255,0));
		printf("目标%d - 面积:%.2f - 周长: %.2f ", i, mu[i].m00, contourArea(contours[i]), arcLength( contours[i], true ) );
		RotatedRect r = fitEllipse(contours.at(i));
		double majorAxis = r.size.height > r.size.width ? r.size.height : r.size.width;//长轴大小
		double minorAxis = r.size.height > r.size.width ? r.size.width : r.size.height;//短轴大小
		double area = mu[i].m00;//面积
		int perimeter = arcLength(contours.at(i), true);
		double orientation = r.angle;
		double orientation_rads = orientation*3.1416/180;
		printf("- 偏移角度: %.1f\n\n", orientation);
		double diameter = sqrt((4*area)/3.1416);//直径
		double eccentricity = sqrt(1-pow(minorAxis/majorAxis,2));//离心率
		double roundness = pow(perimeter, 2)/(2*3.1416*area);//圆滑度
		line(drawing, Point(mc[i].x, mc[i].y), Point(mc[i].x+30*cos(orientation_rads), mc[i].y+30*sin(orientation_rads)), cvScalar(0,0,200), 3);
		char tam[100];
		sprintf(tam, "%.2f", orientation);
		putText(drawing, tam, Point(mc[i].x, mc[i].y), FONT_HERSHEY_SIMPLEX, 0.5, cvScalar(0,220,120),1.5);
	}
	namedWindow( "Contours", CV_WINDOW_AUTOSIZE );
	imshow( "Contours", drawing );
	moveWindow("Contours",1100,20);
	waitKey(0);
	src.release();
	src_gray.release();
	return 0;
}
           

参考地址:https://www.it610.com/article/3982350.htm

二 :Hu矩简要说明

Hu矩特性:具有旋转,缩放和平移不变性。

由Hu矩组成的特征量对图片进行识别,优点就是速度很快,缺点是识别率比较低。 因此Hu不变矩一般用来识别图像中大的物体,对于物体的形状描述得比较好,图像的纹理特征不能太复杂