OpenCV-图像处理(31、图像矩(Image Moments))

版权声明:本文由 Micheal 超 博客 创作,未经博主允许不得转载。 https://blog.csdn.net/qq_42887760/article/details/86585701

矩的概念介绍

可以参考:https://blog.csdn.net/keith_bb/article/details/70197104

  • 几何矩( 其中P(i,j)为图像在坐标点(i,j)处的灰度值。)
    在这里插入图片描述
  • 中心距在这里插入图片描述
  • 中心归一化距
    在这里插入图片描述
    其中:图像中心Center(x0, y0)。 此非图像坐标的中心点,而是图像 质 的中心,质点
    在这里插入图片描述

API介绍与使用 – cv::moments 计算生成数据

在这里插入图片描述

API介绍与使用-计算矩cv::moments

opencv中提供了moments()来计算图像中的中心矩(最高到三阶),HuMoments()用于由中心矩计算Hu矩.同时配合函数contourArea函数计算轮廓面积和arcLength来计算轮廓或曲线长度

  • moments( // 计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
    InputArray array,//输入数据,findContours 找到的轮廓数据
    bool binaryImage=false // 是否为二值图像
    )

    1. array:输入数组,可以是光栅图像(单通道,8-bit或浮点型二维数组),或者是一个二维数组(1 X N或N X 1),二维数组类型为Point或Point2f
    2. binaryImage:默认值是false,如果为true,则所有非零的像素都会按值1对待,也就是说相当于对图像进行了二值化处理,阈值为1,此参数仅对图像有效。
  • contourArea(
    InputArray contour,//输入轮廓数据
    bool oriented// 默认false、返回绝对值)

    1. contour:是一个向量,二维点,可以是vector或Mat类型
    2. oriented:有默认值false,面向区域标识符,如果为true,该函数返回一个带符号的面积,其正负取决于轮廓的方向(顺时针还是逆时针)。根据这个特性可以根据面积的符号来确定轮廓的位置。如果是默认值false,则面积以绝对值的形式返回.
    3. 该函数使用Green formula计算轮廓面积,返回面积和非零像素数量如果使用drawContours或fillPoly绘制轮廓,可能导致不同。
  • arcLength( //用于计算封闭轮廓的周长或曲线的长度
    InputArray curve,//输入曲线数据
    bool closed// 是否是封闭曲线)

    1. curve:输入二维点集,可以是vector或Mat类型
    2. closed:曲线是否封闭的标志位,true则封闭否则不封闭

演示代码-步骤

在这里插入图片描述

  1. 提取图像边缘
  2. 发现轮廓
    在这里插入图片描述
  3. 计算每个轮廓对象的矩
    在这里插入图片描述
  4. 计算每个对象的中心、弧长、面积
    在这里插入图片描述

程序代码

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

//定义全局变量
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
 //声明回调函数
void thresh_callback(int, void* );
 
int main( int argc, char** argv )
{
	// 读入原图像, 返回3通道图像数据
	src = imread("E:/Experiment/OpenCV/Pictures/CircleTest2.jpg");
	// 创建新窗口
	char* source_window = "Source";
	namedWindow( source_window, CV_WINDOW_AUTOSIZE );
	imshow( source_window, src );

	// 把原图像转化成灰度图像并进行平滑
	cvtColor( src, src_gray, CV_BGR2GRAY );
	//blur( src_gray, src_gray, Size(3,3) );
	GaussianBlur(src_gray, src_gray, Size(3, 3), 0, 0);//这里用高斯模糊去噪,相比于均值,轮廓发现的准确
	imshow("灰度图", src_gray);

 
	createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
	thresh_callback( thresh, 0 );
 
	waitKey(0);
	return(0);
}
 
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++ ){
		//计算矩,返回 0阶到3阶所有的几何矩,2阶到3阶所有的中心矩,2阶到3阶所有的中心归一矩
		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 );
	}
}

运行截图

在这里插入图片描述
在这里插入图片描述

参考博客

  1. https://blog.csdn.net/keith_bb/article/details/70197104
  2. https://blog.csdn.net/huanghuangjin/article/details/81189586
  3. https://blog.csdn.net/LYKymy/article/details/83210439

猜你喜欢

转载自blog.csdn.net/qq_42887760/article/details/86585701
今日推荐