[OpenCV] Extraction of Continuous Area Computing Area Descriptor

Posted by vtroubled on Wed, 31 Jul 2019 01:16:25 +0200

First, read the image and gray it.

	cv::Mat srcImg = cv::imread("group.jpg");
	if (srcImg.empty())
	{
		cout << "error";
		return -1;
	}
	cv::namedWindow("SRC", CV_WINDOW_AUTOSIZE);
	cv::imshow("SRC", srcImg);

	cv::Mat srcGray;
	cv::cvtColor(srcImg, srcGray, cv::COLOR_RGB2GRAY);
	cv::namedWindow("GRAY", CV_WINDOW_AUTOSIZE);
	cv::imshow("GRAY", srcGray);

The gray image is binarized.

	cv::Mat thesImg;
	cv::threshold(srcGray, thesImg, 60, 255, cv::THRESH_BINARY);
	cv::namedWindow("THRESHOLD", CV_WINDOW_AUTOSIZE);
	cv::imshow("THRESHOLD", thesImg);

Morphological filtering is applied to binary image, which first opens and then closes to remove noise. In order to facilitate subsequent display, the results are reversed.

	cv::Mat element(5, 5, CV_8U, cv::Scalar(1));
	cv::Mat opened;
	cv::morphologyEx(thesImg, opened, cv::MORPH_OPEN, element);
	cv::Mat closed;
	cv::morphologyEx(opened, closed, cv::MORPH_CLOSE, element);


	cv::Mat morphInv = 255 - closed;
	cv::namedWindow("MORPH", CV_WINDOW_AUTOSIZE);
	cv::imshow("MORPH", morphInv);

OpenCV provides a function to extract contours of contiguous regions in an image. Its prototype function is

void cv::findContours(InputOutputArray image,
    OutputArrayOfArrays contours,
    OutputArray hierarchy,
    int mode,
    int method,
    Point offset = Point() 
)	

Where the value of mode is in the enumeration type cv::RetrievalModes in

 

The method value is taken in the enumeration type cv::ContourApproximationModes in

	std::vector<std::vector<cv::Point>> contours;
	cv::findContours(morphInv, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
	cv::Mat result(opened.size(), CV_8U, cv::Scalar(255));
	cv::drawContours(result, contours, -1, 0, 2);
	cv::namedWindow("CONTOURS", CV_WINDOW_AUTOSIZE);
	cv::imshow("CONTOURS", result);

 

If the size of the object of interest is known beforehand, the continuous regions identified can be analyzed independently, and some regions can be deleted.

	int cmin = 50;
	int cmax = 500;
	std::vector<std::vector<cv::Point>>::iterator it = contours.begin();
	while (it != contours.end())
	{
		if (it->size() < cmin || it->size() > cmax)
		{
			it = contours.erase(it);
		}
		else
		{
			++it;
		}
	}

There are many functions for shape description in OpenCV.

	cv::Rect r0 = cv::boundingRect(contours[0]);//Boundary box
	cv::rectangle(result, r0, 0, 2);//Draw a rectangle

	float radius;
	cv::Point2f center;
	cv::minEnclosingCircle(contours[1], center, radius);//Covering circle
	cv::circle(result, center, static_cast<int>(radius), cv::Scalar(0), 2);//Circle drawing

	std::vector<cv::Point> poly;
	cv::approxPolyDP(contours[2], poly, 5, true);//Polygonal approximation
	cv::polylines(result, poly, true, 0, 2);//Polygon

	std::vector<cv::Point> hull;
	cv::convexHull(contours[3], hull);//convex hull
	cv::polylines(result, hull, true, 0, 2);

	std::vector<std::vector<cv::Point>>::iterator itc = contours.begin();
	while (itc != contours.end())
	{
		cv::Moments mom = cv::moments(cv::Mat(*itc++));//Contour moment
		cv::circle(result, cv::Point(mom.m10 / mom.m00, mom.m01 / mom.m00), 2, cv::Scalar(0), 2);//Draw the center of gravity
	}

	cv::namedWindow("SHAPE", CV_WINDOW_AUTOSIZE);
	cv::imshow("SHAPE", result);

Topics: OpenCV