最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?OpenCV實現(xiàn)物體尺寸測量示例詳解

 更新時間:2022年01月10日 14:31:13   作者:Zero___Chen  
本文主要介紹了利用OpenCV對物體的尺寸進(jìn)行測量,即先定位到待測物體的位置,然后測量物體的寬高。感興趣的同學(xué)可以跟隨小編一起學(xué)習(xí)學(xué)習(xí)

前言

本文將使用OpenCV C++ 進(jìn)行物體尺寸測量。具體來說就是先定位到待測物體的位置,然后測量物體的寬高。

一、圖像透視矯正

原圖如圖所示。本案例的需求是測量圖片中兩張卡片的尺寸。首先,我們得定位到兩張卡片的位置。第一步,我們首先得將白色A4紙切割出來,這樣方便定位到兩張卡片所在位置。這里用到的算法是圖像透視矯正,具體可以參考OpenCV C++案例實戰(zhàn)四《圖像透視矯正》

//圖像矯正
void getWarp(Mat src, Mat &Warp)
{
	Mat gray;
	cvtColor(src, gray, COLOR_BGR2GRAY);

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

	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
	Mat open;
	morphologyEx(thresh, open, MORPH_OPEN, kernel);

	vector<vector<Point>>contours;
	findContours(open, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	vector<vector<Point>>conPoly(contours.size());
	vector<Point>srcPts;

	//找到最大輪廓
	int MaxIndex = 0;
	double Area = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);
		if (area > Area)
		{
			Area = area;
			MaxIndex = i;
		}
	}

	//獲取矩形四個角點(diǎn)
	double peri = arcLength(contours[MaxIndex], true);
	approxPolyDP(contours[MaxIndex], conPoly[MaxIndex], 0.02*peri, true);

	srcPts = { conPoly[MaxIndex][0],conPoly[MaxIndex][1],conPoly[MaxIndex][2],conPoly[MaxIndex][3] };

	int T_L, B_L, B_R, T_R;
	int width = src.cols / 2;
	int height = src.rows / 2;
	for (int i = 0; i < srcPts.size(); i++)
	{
		if (srcPts[i].x < width && srcPts[i].y < height)
		{
			T_L = i;
		}
		if (srcPts[i].x < width && srcPts[i].y > height)
		{
			B_L = i;
		}
		if (srcPts[i].x > width && srcPts[i].y > height)
		{
			B_R = i;
		}
		if (srcPts[i].x > width && srcPts[i].y < height)
		{
			T_R = i;
		}
	}

	double UpWidth = EuDis(srcPts[T_L], srcPts[T_R]);
	double DownWidth = EuDis(srcPts[B_L], srcPts[B_R]);
	double MaxWidth = max(UpWidth, DownWidth);

	double UpHeight = EuDis(srcPts[T_L], srcPts[B_L]);
	double DownHeight = EuDis(srcPts[T_R], srcPts[B_R]);
	double MaxHeight = max(UpHeight, DownHeight);

	//透視變換進(jìn)行圖像矯正
	Point2f SrcAffinePts[4] = { Point2f(srcPts[T_L]),Point2f(srcPts[T_R]) ,Point2f(srcPts[B_R]) ,Point2f(srcPts[B_L]) };
	Point2f DstAffinePts[4] = { Point2f(0,0),Point2f(MaxWidth,0),Point2f(MaxWidth,MaxHeight),Point2f(0,MaxHeight) };

	Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
	warpPerspective(src, Warp, M, Point(MaxWidth, MaxHeight));

}

效果如圖所示。接下來,我們需要定位兩張卡片所在位置,尋找特征。

二、物體定位

//獲取物體坐標(biāo)
void FindPts(Mat &Warp, vector<vector<Point>>&TargetPts)
{

	Mat gray;
	cvtColor(Warp, gray, COLOR_BGR2GRAY);

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

	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
	Mat open;
	morphologyEx(thresh, open, MORPH_OPEN, kernel);

	vector<vector<Point>>contours;
	findContours(open, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	vector<vector<Point>>conPoly(contours.size());
	//定位卡片四個角點(diǎn)
	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);

		if (area > 1000)
		{
			double peri = arcLength(contours[i], true);

			approxPolyDP(contours[i], conPoly[i], 0.02*peri, true);

			vector<Point>temp;
			temp = { conPoly[i][0],conPoly[i][1], conPoly[i][2], conPoly[i][3] };

			TargetPts.push_back(temp);
		}
	}
}

如圖所示。通過上面代碼段,我們已經(jīng)定位出卡片的四個角點(diǎn)。接下來,只需根據(jù)角點(diǎn)位置就可以計算卡片的寬高了。

三、尺寸測量

//計算距離
void DrawAndCompute(Mat &Warp, vector<vector<Point>>&TargetPts)
{
	for (int i = 0; i < TargetPts.size(); i++)
	{
		for (int j = 0; j < TargetPts[i].size(); j++)
		{
			//尺寸測量
			Point PtA = Point(TargetPts[i][j]);
			Point PtB = Point(TargetPts[i][(j + 1) % TargetPts[i].size()]);
			double dis = round(EuDis(PtA, PtB) * 100) / 100;

			//效果顯示
			circle(Warp, TargetPts[i][j], 5, Scalar(0, 255, 0), -1);
			line(Warp, PtA, PtB, Scalar(0, 0, 255), 2);
			char text[20];
			sprintf_s(text, "%.2f", dis);
			Point point = Point((PtA.x + PtB.x) / 2, (PtA.y + PtB.y) / 2);
			putText(Warp, text, point, FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 255), 2);
		}
	}
}

四、效果顯示

五、源碼

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

//歐式距離
double EuDis(Point pt1, Point pt2)
{
	return sqrt((pt2.x - pt1.x)*(pt2.x - pt1.x) + (pt2.y - pt1.y)*(pt2.y - pt1.y));
}

//圖像矯正
void getWarp(Mat src, Mat &Warp)
{
	Mat gray;
	cvtColor(src, gray, COLOR_BGR2GRAY);

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

	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
	Mat open;
	morphologyEx(thresh, open, MORPH_OPEN, kernel);

	vector<vector<Point>>contours;
	findContours(open, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	vector<vector<Point>>conPoly(contours.size());
	vector<Point>srcPts;

	//找到最大輪廓
	int MaxIndex = 0;
	double Area = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);
		if (area > Area)
		{
			Area = area;
			MaxIndex = i;
		}
	}

	//獲取矩形四個角點(diǎn)
	double peri = arcLength(contours[MaxIndex], true);
	approxPolyDP(contours[MaxIndex], conPoly[MaxIndex], 0.02*peri, true);

	srcPts = { conPoly[MaxIndex][0],conPoly[MaxIndex][1],conPoly[MaxIndex][2],conPoly[MaxIndex][3] };

	int T_L, B_L, B_R, T_R;
	int width = src.cols / 2;
	int height = src.rows / 2;
	for (int i = 0; i < srcPts.size(); i++)
	{
		if (srcPts[i].x < width && srcPts[i].y < height)
		{
			T_L = i;
		}
		if (srcPts[i].x < width && srcPts[i].y > height)
		{
			B_L = i;
		}
		if (srcPts[i].x > width && srcPts[i].y > height)
		{
			B_R = i;
		}
		if (srcPts[i].x > width && srcPts[i].y < height)
		{
			T_R = i;
		}
	}

	double UpWidth = EuDis(srcPts[T_L], srcPts[T_R]);
	double DownWidth = EuDis(srcPts[B_L], srcPts[B_R]);
	double MaxWidth = max(UpWidth, DownWidth);

	double UpHeight = EuDis(srcPts[T_L], srcPts[B_L]);
	double DownHeight = EuDis(srcPts[T_R], srcPts[B_R]);
	double MaxHeight = max(UpHeight, DownHeight);

	//透視變換進(jìn)行圖像矯正
	Point2f SrcAffinePts[4] = { Point2f(srcPts[T_L]),Point2f(srcPts[T_R]) ,Point2f(srcPts[B_R]) ,Point2f(srcPts[B_L]) };
	Point2f DstAffinePts[4] = { Point2f(0,0),Point2f(MaxWidth,0),Point2f(MaxWidth,MaxHeight),Point2f(0,MaxHeight) };

	Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
	warpPerspective(src, Warp, M, Point(MaxWidth, MaxHeight));

}

//獲取物體坐標(biāo)
void FindPts(Mat &Warp, vector<vector<Point>>&TargetPts)
{

	Mat gray;
	cvtColor(Warp, gray, COLOR_BGR2GRAY);

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

	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
	Mat open;
	morphologyEx(thresh, open, MORPH_OPEN, kernel);

	vector<vector<Point>>contours;
	findContours(open, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	vector<vector<Point>>conPoly(contours.size());
	//定位卡片四個角點(diǎn)
	for (int i = 0; i < contours.size(); i++)
	{
		double area = contourArea(contours[i]);

		if (area > 1000)
		{
			double peri = arcLength(contours[i], true);

			approxPolyDP(contours[i], conPoly[i], 0.02*peri, true);

			vector<Point>temp;
			temp = { conPoly[i][0],conPoly[i][1], conPoly[i][2], conPoly[i][3] };

			TargetPts.push_back(temp);
		}
	}
}

//計算距離
void DrawAndCompute(Mat &Warp, vector<vector<Point>>&TargetPts)
{
	for (int i = 0; i < TargetPts.size(); i++)
	{
		for (int j = 0; j < TargetPts[i].size(); j++)
		{
			//尺寸測量
			Point PtA = Point(TargetPts[i][j]);
			Point PtB = Point(TargetPts[i][(j + 1) % TargetPts[i].size()]);
			double dis = round(EuDis(PtA, PtB) * 100) / 100;

			//效果顯示
			circle(Warp, TargetPts[i][j], 5, Scalar(0, 255, 0), -1);
			line(Warp, PtA, PtB, Scalar(0, 0, 255), 2);
			char text[20];
			sprintf_s(text, "%.2f", dis);
			Point point = Point((PtA.x + PtB.x) / 2, (PtA.y + PtB.y) / 2);
			putText(Warp, text, point, FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 0, 255), 2);
		}
	}
}

int main()
{
	Mat src = imread("src.jpg");
	if (src.empty())
	{
		cout << "No Image!" << endl;
		system("pause");
		return -1;
	}

	Mat Warp;
	getWarp(src, Warp);

	vector<vector<Point>>TargetPts;	
	FindPts(Warp, TargetPts);

	DrawAndCompute(Warp, TargetPts);

	imshow("Warp", Warp);
	waitKey(0);
	destroyAllWindows();
	system("pause");
	return 0;
}

總結(jié)

本文使用OpenCV C++ 進(jìn)行物體尺寸測量,關(guān)鍵步驟有以下幾點(diǎn)。

1、圖像透視矯正。方便定位物體所在位置。

2、物體定位。定位所需物體位置,獲取特征。

3、根據(jù)已知特征進(jìn)行計算。

以上就是C++ OpenCV實現(xiàn)物體尺寸測量示例詳解的詳細(xì)內(nèi)容,更多關(guān)于C++ OpenCV物體尺寸測量的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++中字符串以及數(shù)組和指針的互相使用講解

    C++中字符串以及數(shù)組和指針的互相使用講解

    這篇文章主要介紹了C++中字符串以及數(shù)組和指針的互相使用講解,是C++入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-09-09
  • C語言編程入門必背的示例代碼整理大全

    C語言編程入門必背的示例代碼整理大全

    這篇文章主要為大家整理并介紹了C語言編程必背的示例代碼大全,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • C++與QML進(jìn)行數(shù)據(jù)交互的常見方法總結(jié)

    C++與QML進(jìn)行數(shù)據(jù)交互的常見方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了C++與QML進(jìn)行數(shù)據(jù)交互的常見方法,文中 的示例代碼講解詳細(xì),具有一定的參考價值,有需要的小伙伴可以跟隨小編一起了解一下
    2023-10-10
  • C語言求逆矩陣案例詳解

    C語言求逆矩陣案例詳解

    這篇文章主要介紹了C語言求逆矩陣案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • cmake 學(xué)習(xí)筆記

    cmake 學(xué)習(xí)筆記

    這篇文章主要介紹了作者學(xué)習(xí)cmake 的相關(guān)資料與心得,有需要的小伙伴可以參考下
    2017-07-07
  • C++多態(tài)的實現(xiàn)及原理詳細(xì)解析

    C++多態(tài)的實現(xiàn)及原理詳細(xì)解析

    C++的多態(tài)性用一句話概括就是:在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運(yùn)行時將會根據(jù)對象的實際類型來調(diào)用相應(yīng)的函數(shù)。如果對象類型是派生類,就調(diào)用派生類的函數(shù);如果對象類型是基類,就調(diào)用基類的函數(shù)
    2013-09-09
  • 基于實現(xiàn)Qt秒表設(shè)計

    基于實現(xiàn)Qt秒表設(shè)計

    這篇文章主要為大家詳細(xì)介紹了基于實現(xiàn)Qt秒表設(shè)計,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • C語言動態(tài)內(nèi)存函數(shù)詳解

    C語言動態(tài)內(nèi)存函數(shù)詳解

    這篇文章主要介紹了C語言動態(tài)內(nèi)存函數(shù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • C語言實現(xiàn)簡單推箱子游戲

    C語言實現(xiàn)簡單推箱子游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實現(xiàn)簡單推箱子游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 一起來練習(xí)C++的指針

    一起來練習(xí)C++的指針

    這篇文章主要為大家詳細(xì)介紹了C++的指針,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03

最新評論

建宁县| 大厂| 什邡市| 灌阳县| 芮城县| 津南区| 万全县| 手游| 崇信县| 佛学| 裕民县| 金堂县| 临高县| 霞浦县| 大厂| 石门县| 乌兰察布市| 天台县| 扎赉特旗| 米泉市| 邓州市| 新乐市| 清新县| 乌兰察布市| 大化| 万山特区| 孝感市| 苏尼特左旗| 苍梧县| 融水| 建德市| 红河县| 夏津县| 弥渡县| 舒城县| 长顺县| 福海县| 武川县| 东辽县| 平潭县| 阿坝县|