openCV 轮廓查找-测量物体尺寸

一,利用openCV的findContours轮廓查找功能,用已知物体的尺寸(比如硬币)作为参考,根据实际尺寸与像素尺寸的比列,求出图片中物体的实际大小。存在的问题有两个:

  • 图片的阴影导致轮廓不准确,除了多给点光之外没有想到怎么消除阴影。
  • 拍摄的角度要求垂直物体,这个也很难做到,可以靠工装固定,目前不知道怎么用算法来规避。

二,流程

openCV 轮廓查找-测量物体尺寸_第1张图片

三,代码

#include "stdafx.h"
#include 

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/background_segm.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
#include 
using namespace std;
using namespace cv;

Mat g_srcImage;
Mat g_grayImage;

const int g_dReferWidth=19;//mm 
double g_dPixelsPerMetric;
vector> g_vContours;
vector g_vHierarchy;
bool g_bFirst=true;

static cv::Point2f midpoint(cv::Point2f& ptA, cv::Point2f& ptB);//求中点 
static float getDistance(Point2f pointA, Point2f pointB);//求距离
static bool ContoursSortFun(vector contour1, vector contour2);//按照 x坐标 排序
//-----------------------------------【main( )函数】--------------------------------------------
//      描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main(int argc, const char** argv)
{
	system("color 1F");

	g_srcImage = imread("1.jpg", 1);
	//灰度 降低计算量
	cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);
	
	//高斯滤波 降噪
	GaussianBlur(g_grayImage, g_grayImage, Size(7, 7), 0);
	imshow("高斯滤波", g_grayImage);
	
	//边缘检测
	Canny(g_grayImage, g_grayImage, 50,100);

	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); //隔开物体
	dilate(g_grayImage, g_grayImage, element);//膨胀
	erode(g_grayImage, g_grayImage, element);//腐蚀
	imshow("形态学", g_grayImage);

	//寻找轮廓
	findContours(g_grayImage, g_vContours, g_vHierarchy, CV_RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	
	std::sort(g_vContours.begin(),g_vContours.end(), ContoursSortFun);//按照从左到右 排序
	for (unsigned i = 0; i < g_vContours.size(); i++) {
		
		if (contourArea(g_vContours[i]) < 100)//面积太小 则忽略
			continue;

		RotatedRect box = minAreaRect(g_vContours[i]);
		Point2f boxPoints[4];
		box.points(boxPoints);

		Point2f pointA = midpoint(boxPoints[0], boxPoints[1]);
		Point2f pointB = midpoint(boxPoints[1], boxPoints[2]);
		Point2f pointC = midpoint(boxPoints[2], boxPoints[3]);
		Point2f pointD = midpoint(boxPoints[3], boxPoints[0]);

		circle(g_srcImage, pointA, 2, Scalar(0, 0, 255));
		circle(g_srcImage, pointB, 2, Scalar(0, 0, 255));
		circle(g_srcImage, pointC, 2, Scalar(0, 0, 255));
		circle(g_srcImage, pointD, 2, Scalar(0, 0, 255));

		line(g_srcImage, pointA, pointC, Scalar(255, 0, 0));
		line(g_srcImage, pointD, pointB, Scalar(255, 0, 0));

		double dWidth = getDistance(pointA, pointC);
		double dHeight = getDistance(pointD, pointB);
		if (g_bFirst) {
			g_dPixelsPerMetric = dWidth/g_dReferWidth; //计算像素与 实际大小的比列
			cout << "pixelPerMetric:" << dWidth <<" "<< g_dReferWidth <<"  "<< g_dPixelsPerMetric;
			g_bFirst = false;
		}

		cout << "dWidth" << dWidth <<"   "<< dHeight<< "      "< contour1, vector contour2) {
	return  (contour1[0].x

四,效果

openCV 轮廓查找-测量物体尺寸_第2张图片

 

 

参考:https://blog.csdn.net/happyjacob/article/details/81055275

 

你可能感兴趣的:(C++)