OpenCV C++ Case Practice Eight "Contour Matching Based on Hu Moments"

OpenCV C++ Case Practice Eight "Contour Matching Based on Hu Moments"


foreword

This article will use OpenCV C++ to perform contour matching based on Hu moment.

1. Find the outline

Original image
Please add a picture description
Test image
Please add a picture description

vector<vector<Point>>findContour(Mat Image)
{
    
    
	Mat gray;
	cvtColor(Image, gray, COLOR_BGR2GRAY);

	Mat thresh;
	threshold(gray, thresh, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

	vector<vector<Point>>contours;
	findContours(thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	vector<vector<Point>>EffectConts;
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		double area = contourArea(contours[i]);

		if (area > 1000)
		{
    
    
			EffectConts.push_back(contours[i]);
		}
	}

	return EffectConts;
}

Please add a picture description
As shown, this is the outermost contour found. Next, we perform matching based on contours.

Second, calculate the Hu moment

OpenCV provides the moments API to calculate the central moment of the image; the HuMoments API is used to calculate the Hu moment from the central moment. Please search for the relevant knowledge about moments HuMoments by yourself.

	Moments m_test = moments(test_contours[0]);
	Mat hu_test;
	HuMoments(m_test, hu_test);

	double MinDis = 1000;
	int MinIndex = 0;
	for (int i = 0; i < src_contours.size(); i++)
	{
    
    
		Moments m_src = moments(src_contours[i]);
		Mat hu_src;
		HuMoments(m_src, hu_src);

		double dist = matchShapes(hu_test, hu_src, CONTOURS_MATCH_I1, 0);

		if (dist < MinDis)
		{
    
    
			MinDis = dist;
			MinIndex = i;
		}
	}

The general idea of ​​the above code segment is: first calculate the Hu moment of the test image; then use a for loop to calculate the Hu moment of all the contours in the original image, and then calculate the similarity between the two Hu moments. Here two Hu moments are computed using the matchShapes API. The return value of the function represents the similarity of the two Hu moments. Exactly the same returns a value of 0. That is, by calculating the similarity between the two Hu moments, find the one with the smallest return value as a successful match.

3. Display effect

	drawContours(src, src_contours, MinIndex, Scalar(0, 255, 0), 2);

	Rect rect = boundingRect(src_contours[MinIndex]);

	rectangle(src, rect, Scalar(0, 0, 255), 2);

The final effect is shown in the figure.
Please add a picture description
Please add a picture description

4. Source code

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


vector<vector<Point>>findContour(Mat Image)
{
    
    
	Mat gray;
	cvtColor(Image, gray, COLOR_BGR2GRAY);

	Mat thresh;
	threshold(gray, thresh, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);

	vector<vector<Point>>contours;
	findContours(thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	vector<vector<Point>>EffectConts;
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		double area = contourArea(contours[i]);

		if (area > 1000)
		{
    
    
			EffectConts.push_back(contours[i]);
		}
	}

	return EffectConts;
}


int main()
{
    
    

	Mat src = imread("test/hand.jpg");
	Mat test = imread("test/test-3.jpg");

	if (src.empty() || test.empty())
	{
    
    
		cout << "No Image!" << endl;
		system("pause");
		return -1;
	}

	vector<vector<Point>>src_contours;
	vector<vector<Point>>test_contours;

	src_contours = findContour(src);
	test_contours = findContour(test);

	Moments m_test = moments(test_contours[0]);
	Mat hu_test;
	HuMoments(m_test, hu_test);

	double MinDis = 1000;
	int MinIndex = 0;
	for (int i = 0; i < src_contours.size(); i++)
	{
    
    
		Moments m_src = moments(src_contours[i]);
		Mat hu_src;
		HuMoments(m_src, hu_src);

		double dist = matchShapes(hu_test, hu_src, CONTOURS_MATCH_I1, 0);

		if (dist < MinDis)
		{
    
    
			MinDis = dist;
			MinIndex = i;
		}
	}

	drawContours(src, src_contours, MinIndex, Scalar(0, 255, 0), 2);

	Rect rect = boundingRect(src_contours[MinIndex]);

	rectangle(src, rect, Scalar(0, 0, 255), 2);

	imshow("test", test);
	imshow("Demo", src);
	waitKey(0);
	system("pause");
	return 0;
}

Summarize

This article uses OpenCV C++ based on Hu moment contour matching, the key steps are as follows.
1. Find the outline. Here, I am matching based on the outermost contour.
2. Calculate the Hu moment of the contour, and then use matchShapes to calculate the distance between the two Hu moments to determine the degree of matching.

Guess you like

Origin blog.csdn.net/Zero___Chen/article/details/122008672