Opencv 笔记11 图像的矩原理解析

一、数学中的矩

矩是概率与统计中的一个概念,假设有随机变量X,常数c,正整数k,则有

E[(X−c)k]称X为c 的k阶矩。

1.c=0->ak=E(Xk)称为X的k阶原点矩

2. c=E(X)。这时μk=E[(X−EX)k]称为X的k阶中心矩

同理当随机变量是X 、Y的二维时候有如下:

1、A1=A2=0->上式称为X的p+q阶混合原点矩

2.  A1=E(X),A2=E(Y)->上式称为X的p+q阶混合中心矩

这里只说离散的情况。联系的不谈

二、图像中的几何矩

假设二维图像坐标(x,y)对应的p、q对应的公式:

 三、Hu矩

Hu矩具有旋转、平移等不变性,所以Hu矩在图像中用的更加广泛,Hu矩是有二阶和三阶中心矩得到的七个不变矩,

原点矩:          

 中心矩:          

 归一化中心矩:

四、算子解释与使用

矩:moments()函数用于计算中心矩

moments(InputArray  array, //计算矩的区域2D像素坐标集合或者单通道的CV_8U图像
bool  binaryImage = false //是否将所有非0像素值视为1的标志
)

Hu矩:基于moments()的HuMoments

void HuMoments( 
const Moments& moments, // moments即为上面一个函数计算得到的moments类型
 double* hu // hu是一个含有7个数的数组,就是上面第三种说的7个不变矩)

利用Hu矩进行轮廓匹配的matchShapes()函数

double cv::matchShapes
(InputArray  contour1,  // 目标图像、轮廓
InputArray  contour2, // 模板图像、轮廓
int  method,    // 匹配的方法:  CONTOURS_MATCH_I1
                                CONTOURS_MATCH_I2
                                CONTOURS_MATCH_I3
double  parameter 
)

1、找到图像的质心和轮廓:

 

 代码显示:

Mat src, gray_src;
int threshold_value = 80;
int max_threshold = 255;

const char* output_win = "resultImage";
const char* trackbar_title = "Threshold:";

void Callback_Moments(int, void*) {

	vector<vector<Point>> contours;
	vector<Vec4i> h;
	Mat cannyImage;
	//canny
	Canny(gray_src, cannyImage, threshold_value, threshold_value * 2, 3, false);
	imshow("Canny", cannyImage);
	// 找轮廓
	findContours(cannyImage, contours, h, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); // 找最外层的轮廓

	// 找到轮廓个数个矩
	vector<Moments> contours_moments(contours.size());
	// 质心
	vector<Point2f> centers(contours.size());



	for (int i = 0; i < contours.size(); i++)
	{
		contours_moments[i] = moments(contours[i]);
		centers[i] = Point(
			(static_cast<float>(contours_moments[i].m10 / contours_moments[i].m00)), // x0
			(static_cast<float>(contours_moments[i].m01 / contours_moments[i].m00)));//y0
	}
	printf("%d\n", contours.size());


	// 画出轮廓和各个轮廓对应的质心
	Mat resultImage;
	cannyImage.copyTo(resultImage);
	for (int i = 0; i < contours.size(); i++)
	{
		if (contourArea(contours[i]) < 1000) { // 轮廓的面积都是>1000的
			continue;
		}

		printf("质心坐标 x : %.2f y : %.2f\n", centers[i].x, centers[i].y);
		printf("contours %d area : %.2f   arc length : %.2f\n", i, contourArea(contours[i]), arcLength(contours[i], true));
		drawContours(resultImage, contours, i, Scalar(255, 255, 255), 2, 8, h, 0);
		circle(resultImage, centers[i], 3, Scalar(255, 255, 255), 6, 8);
	}

	imshow(output_win, resultImage);
}

int main() {
	src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\513.png");
	if (!src.data)
	{
		cout << "could not load image !";
		waitKey(0);
		return -1;
	}
	cvtColor(src, gray_src, CV_BGR2GRAY);
	GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);

	namedWindow(output_win, CV_WINDOW_AUTOSIZE);
	imshow("原图", src);

	createTrackbar("Threshold", output_win, &threshold_value, max_threshold, Callback_Moments);
	Callback_Moments(0, 0);

	waitKey(0);
	return 0;
}

 

Hu矩的模板匹配: 

 


int main() {
	Mat  template_A, src, gray_src,brinaryImage,brinaryImage_A, gray_src_A,result;

	src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\516.png");
	template_A= imread("C:\\Users\\19473\\Desktop\\opencv_images\\517.png");
	if (!src.data)
	{
		cout << "could not load image !";
		waitKey(0);
		return -1;
	}
	imshow("模板图像", template_A);
	imshow("待找图像", src);
	// 1.待测图像-- 灰度图像--》二值图像
	cvtColor(src, gray_src, CV_BGR2GRAY);
	GaussianBlur(gray_src, gray_src, Size(3, 3), 0, 0);
	threshold(gray_src,brinaryImage,10,255,THRESH_BINARY);
	imshow("threshold", brinaryImage);
	vector<vector<Point>>  contours;
	vector<Vec4i> h;// 拓补结构
	// 2、查找轮廓
	findContours(brinaryImage, contours, h, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
	printf("待测图像的轮廓个数 : %d\n", contours.size());



	// 3、模板图像处理
	cvtColor(template_A, gray_src_A, CV_BGR2GRAY);
	threshold(gray_src_A, brinaryImage_A, 10, 255, THRESH_BINARY);
	imshow("A", brinaryImage_A);
	vector<vector<Point>>  contour_A;
	vector<Vec4i> h_A;
	findContours(brinaryImage_A, contour_A, h_A, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0));
	int a = contour_A.size();
	printf("模板图像的轮廓个数 : %d\n", a);



	// 4 在待测图像中寻找
	result = gray_src.clone();
	Moments m_A = moments(contour_A[0]);
	Mat m_A_hu;
    HuMoments(m_A, m_A_hu);
	for (int n = 0; n < contours.size(); n++)
	 {
	     Moments mm = moments(contours[n]);
	     Mat hum;
	     HuMoments(mm, hum);
	     //Hu矩匹配
	         double dist;
	     dist = matchShapes(hum, m_A_hu, CONTOURS_MATCH_I1, 0);
	     if (dist < 1)
	         {
	             drawContours(result, contours, n, Scalar(255,0, 255), 3, 8);
	         }
	 }

	imshow("结果", result);

	waitKey(0);
	return 0;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值