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

C++利用opencv實現單目測距的實現示例

 更新時間:2021年11月11日 09:48:23   作者:知道什么是碼怪嗎?  
本文主要介紹了C++利用opencv實現單目測距的實現示例,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

閑來無事,用C++做了一個簡易的單目測距。算法用的cv自帶的,改改參數就行。實現了讀取照片測距,讀取筆記本攝像頭測距,讀取視頻測距三個功能。

為什么不用雙目測距?因為沒錢買攝像頭……

原理:相似三角形原理,已知焦距的情況下檢測被測物在圖片中所占的像素寬度來判斷被測物與攝像頭的距離,同時也可以得出被測物的大概長寬。注意:攝像頭要和被測物體平行,如果不平行在側面看來攝像頭和物體之間的連線就與水平方向有一個夾角a,被測物體在圖片中的大小會受到影響,從而影響測量效果。

誤差分析:導致測量效果不好的原因有很多,比如說攝像頭與被測物沒有在同一高度,攝像頭標定的焦距不準確,不同視頻拍攝的攝像頭焦距不同,測量出來也不一樣,所以測量前需要對攝像頭進行標定處理得到焦距,這里使用的是傳統(tǒng)的標定方法。

步驟:

①標定得出焦距

②對圖片進行高斯濾波處理(平滑操作,過濾操作,去噪操作)

③邊緣檢測

④畫出檢測出的輪廓并返回最小的外接矩形(可以設置畫出全部輪廓或者是最大的輪廓)

⑤計算距離

檢測攝像頭只需要把攝像頭獲取到的畫面逐幀分析,就相當于對照片分析,視頻也是一個道理。這里我設置了一個保存最小距離和最大距離的變量,當然這只能作為一個參考值并不是準確的,因為攝像頭和視頻測距都沒有和被測物平行。

效果演示:

效果不穩(wěn)定,對于單張圖片效果有時候誤差只有幾厘米,有時候誤差就幾十厘米甚至超過一百厘米。這個測量的距離是圖片中檢測到的最小矩形到攝像頭的距離,所以對于背景比較干凈的矩形圖片很好識別,識別的很規(guī)整,但是對于一些背景雜亂的圖片,識別效果就差強人意。這里以兩種不同的圖片做對比。

其對應的圖片處理效果如下(實際誤差只有1厘米):

對于陽臺的一棵樹:

我也不知道我和這棵樹距離有好遠,測出來163cm,但是肯定超過了這個距離。

代碼(拿了代碼記得點贊評論一波哦):

沒有分文件編寫,配置好opencv就可以直接用,效果不保證,也就圖一樂。

#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;
//2903.85   2438.65   2904.1
#define KNOWN_DISTANCE  70.866		//已知距離
#define KNOWN_WIDTH   0.787		//已知寬度0.787    11.69
#define KNOWN_HEIGHT  0.787	//已知高度0.787    8.27
//需要提前獲取,通過標定步驟獲得的
#define KNOWN_FOCAL_LENGTH  3000  //已知焦距
 
double MaxDistance= DBL_MIN;//最大距離
double MinDistance= DBL_MAX;//最小距離
void GetPicture(Mat& SrcImage, int choice);
void GetCamera(int choice);
void GetVideo(int choice);
double GetTheDistanceToCamera(double KnownWidth, double FocalLength, double PerWidth);
double CalculateFocalDistance(Mat& Image);
RotatedRect FindMarker(Mat& SrcImage);
 
A4紙尺寸:210mm×297mm(16開紙)
int main(int argv, char* argc[])
{	
	int choice = 0;
	cout << "請輸入你想選擇的模式" << endl;
	cout << "識別圖片請輸入:1" << endl;
	cout << "實時攝像頭識別請輸入:2" << endl;
	cout << "讀取視頻請輸入:3" << endl;
	
	cin >> choice;
	if (choice == 1 ){
		Mat SrcImage = imread("輸入圖片絕對路徑在這里.jpg", IMREAD_COLOR);//獲取圖片
		GetPicture(SrcImage,choice);
		cout << "圖像中檢測過的輪廓中,最大距離為:" << MaxDistance << "cm" << endl;
		cout << "圖像中檢測過的輪廓中,最小距離為:" << MinDistance << "cm" << endl;
	}
	else if (choice == 2) {
		GetCamera(choice);
	}
	else if (choice == 3) {
		GetVideo(choice);
	}
	
}
 
void GetPicture(Mat& SrcImage,int choice) {
	
	//以下程序用于標定相機獲得“焦距”
	namedWindow("輸入窗口", 0);
	resizeWindow("輸入窗口", 600, 600);//限定窗口大小
	imshow("輸入窗口", SrcImage);//輸出窗口
	double FocalLength = 0.0;
	FocalLength = CalculateFocalDistance(SrcImage);  //獲得焦距
 
	//以下程序用于實際計算距離
	RotatedRect Marker;
	Marker = FindMarker(SrcImage);
	double DistanceInches = 0.0;
	
	DistanceInches = GetTheDistanceToCamera(KNOWN_WIDTH, KNOWN_FOCAL_LENGTH, Marker.size.width); //計算相機與目標之間的距離
	DistanceInches = DistanceInches * 2.54;  //轉換成cm  1英寸=2.54厘米
	//獲取檢測到的最大最小距離的范圍
 
	if (DistanceInches > MaxDistance)
		MaxDistance = DistanceInches;
	if (DistanceInches < MinDistance)
		MinDistance = DistanceInches;
	cout << "DistanceInches(cm):" << DistanceInches << endl;  //顯示的單位為厘米
	putText(SrcImage, format("distance:%f", DistanceInches), Point(100, 100), FONT_HERSHEY_SIMPLEX, 2, Scalar(0, 0, 255), 10, LINE_8);//在圖片上顯示文本
	namedWindow("輸出窗口", 0);
	resizeWindow("輸出窗口", 600, 600);
	imshow("輸出窗口", SrcImage);
	if (choice != 1) { //如果檢測視頻或者攝像頭,就延時1ms,如果檢測圖片,就停留在當前幀
		waitKey(1);
	}
	else if (choice == 1) {
		waitKey(0);
	}
}
 
void GetCamera(int choice) {
 
	Mat frame;
	VideoCapture capture(0);//讀取視攝像頭實時畫面數據,0默認是筆記本的攝像頭;如果是外接攝像頭,這里改為1
 
	while (true)
	{
		capture >> frame;            //讀取當前幀
		GetPicture(frame,choice);
		int key = waitKey(10);
		if (key == 32) {
			break;
		}
			
	}
	cout << "圖像中檢測過的輪廓中,最大距離為:" << MaxDistance << "cm" << endl;
	cout << "圖像中檢測過的輪廓中,最小距離為:" << MinDistance << "cm" << endl;
	capture.release();     //釋放攝像頭資源
	destroyAllWindows();   //釋放全部窗口
 
}
 
void GetVideo(int choice) {
	VideoCapture capture("視頻的絕對路徑.mp4");
 
	Mat frame;
 
	if (capture.isOpened())  //判斷視頻是否成功打開
	{
		//capture.grab() 從視頻文件或捕獲設備中抓取下一個幀
		while (capture.grab()) {
			capture >> frame;
			GetPicture(frame,choice);
			waitKey(1);
			/*int key = waitKey(10);
			if (key == 32) {
				waitKey(0);
			}
			if (key == 27) {
				break;
			}*/
		}
		
	}
	cout << "圖像中最大距離為:" << MaxDistance << "cm" << endl;
	cout << "圖像中最小距離為:" << MinDistance << "cm" << endl;
	waitKey();
}
 
double GetTheDistanceToCamera(double KnownWidth, double FocalLength, double PerWidth)
{
	return (KnownWidth * FocalLength) / PerWidth; //計算目標到相機的距離   KnownWidth-為已知的目標的寬度  FocalLength-焦距   PerWidth-圖像中寬度的像素數
}
 
RotatedRect FindMarker(Mat& SrcImage)//畫出圖形的邊界并返回最小外接矩形
{
	Mat GrayImage;
	cvtColor(SrcImage, GrayImage, COLOR_BGR2GRAY);//將SrcImage復制給GrayImage
 
	Mat GaussImage;
	//將GrayImage通過高斯濾波處理后存放到GaussImage中
	GaussianBlur(GrayImage, GaussImage, Size(3, 7), 3); //高斯濾波,對圖像進行濾波操作(平滑操作、過濾操作,去噪操作)
 
	Mat EdgeImage;
	Canny(GaussImage, EdgeImage, 100, 200);//邊緣檢測
	
/*這段代碼可省略,只是用來看效果。
	namedWindow("復制圖", 0);
	resizeWindow("復制圖", 600, 600);
	imshow("復制圖", GrayImage);
	namedWindow("高斯濾波處理", 0);
	resizeWindow("高斯濾波處理", 600, 600);
	imshow("高斯濾波處理", GaussImage);
	namedWindow("邊緣檢測處理", 0);
	resizeWindow("邊緣檢測處理", 600, 600);
	imshow("邊緣檢測處理", EdgeImage);
*/
	vector<vector<Point>> Contours;
	vector<Vec4i> Hierarchy;
	findContours(EdgeImage.clone(), Contours, Hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE /*,Point(10,20)*/);//檢測物體輪廓
	double Area = -1;
	int Index = -1;
	for (int i = 0; i < Contours.size(); i++)//得到最大的輪廓然后畫出來,其實是一個點集
	{
		if (contourArea(Contours[i]) > Area)
		{
			Area = contourArea(Contours[i]);
			Index = i;
		}
	}
	//第三個參數為-1的時候就畫出全部輪廓
	drawContours(SrcImage, Contours, -1, Scalar(0, 0, 255), 10, LINE_8);//畫出物體的輪廓
 
	RotatedRect Rorect;
	Rorect = minAreaRect(Contours[Index]);  //得到被測物的最小外接矩形
	return Rorect;
}
 
double CalculateFocalDistance(Mat& Image)//計算拍照相機的焦距
{
	RotatedRect Marker;
	Marker = FindMarker(Image);
	double FocalLength = 0.0;
	double FocalWide = 0.0;
	FocalLength = (Marker.size.height * KNOWN_DISTANCE) / KNOWN_WIDTH;  //計算焦距單位為圖像像素  依據公式: F=(P*D)/W   F-焦距   D-距離   P-像素寬度   W-目標的真實寬度(單位英寸)
	FocalWide = (Marker.size.width * KNOWN_DISTANCE) / KNOWN_HEIGHT;
	cout << "標定焦距:" << FocalLength << endl;
	cout << "標定焦距:" << FocalLength << endl;
	return FocalLength;
	//1857.71
}

有關圖像的算法都是已經封裝好了改參數直接用就行了,沒有涉及到什么需要自己寫的高難度算法。

下面還有一些比較各個邊緣檢測效果的算法代碼:

玩玩就行,原理我也不清楚,只會用現成的。

#include"opencv2/opencv.hpp"
using namespace cv;
using namespace std;
 
void main()
{
	//顯示原圖像
	Mat image = imread("C:/Users/蔣林宏/Desktop/圖片/240A.jpg");
	namedWindow("原圖",0);
	resizeWindow("原圖", 600, 600);
	imshow("原圖", image);
 
	//canny邊緣檢測的簡單用法
	Mat result;
	Canny(image, result, 150, 70);
 
	namedWindow("canny邊緣檢測后的圖像",0);
	resizeWindow("canny邊緣檢測后的圖像", 600, 600);
	imshow("canny邊緣檢測后的圖像", result);
 
	//高階的canny用法,轉成灰度圖,降噪,用canny,最后將得到的邊緣作為掩碼,拷貝原圖到效果圖上,得到彩色邊緣圖
	Mat grayimage, edge;
	cvtColor(image, grayimage, COLOR_BGR2GRAY);
	boxFilter(grayimage, edge, -1, Size(3, 3));
	Canny(edge, edge, 150, 70);
	Mat dst;
	dst = Scalar::all(123);
	image.copyTo(dst, edge);
	
	namedWindow("canny高階邊緣檢測后的圖像",0);
	resizeWindow("canny高階邊緣檢測后的圖像", 600, 600);
	imshow("canny高階邊緣檢測后的圖像", dst);
 
	//sobel算子邊緣檢測
	Mat x_result, y_result;
	Sobel(image, x_result, 0, 1, 0);
	Sobel(image, y_result, 0, 0, 1);
	addWeighted(x_result, 0.5, y_result, 0.5, 0, result);
 
	/*imshow("sobel邊緣檢測后x軸的圖像", x_result);
	imshow("sobel邊緣檢測后y軸的圖像", y_result);*/
	namedWindow("sobel邊緣檢測后的圖像",0);
	resizeWindow("sobel邊緣檢測后的圖像", 600, 600);
	imshow("sobel邊緣檢測后的圖像", result);
 
	//laplacian邊緣檢測
	Laplacian(image, result, 0);
	namedWindow("laplacian邊緣檢測后的圖像",0);
	resizeWindow("laplacian邊緣檢測后的圖像", 600, 600);
	imshow("laplacian邊緣檢測后的圖像", result);
 
	//scharr濾波器
	boxFilter(image, image, -1, Size(3, 3));
	Scharr(image, x_result, 0, 1, 0);
	Scharr(image, x_result, 0, 0, 1);
	addWeighted(x_result, 0.5, y_result, 0.5, 0, result);
	namedWindow("scharr邊緣檢測后的圖像",0);
	resizeWindow("scharr邊緣檢測后的圖像", 600, 600);
	imshow("scharr邊緣檢測后的圖像", result);
	waitKey();
}

效果:

說實話有點陰森。

到此這篇關于C++利用opencv實現單目測距的實現示例的文章就介紹到這了,更多相關C++ opencv單目測距內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++實現景區(qū)信息管理系統(tǒng)

    C++實現景區(qū)信息管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現景區(qū)信息管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言實現掃雷游戲源代碼

    C語言實現掃雷游戲源代碼

    這篇文章主要為大家詳細介紹了C語言實現掃雷游戲源代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 如何寫出優(yōu)美的C語言代碼

    如何寫出優(yōu)美的C語言代碼

    今天小編就為大家分享一篇關于如何寫出優(yōu)美的C語言代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • C++實現選擇性排序(SelectionSort)

    C++實現選擇性排序(SelectionSort)

    這篇文章主要為大家詳細介紹了C++實現選擇性排序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++實現求動態(tài)矩陣各元素的和

    C++實現求動態(tài)矩陣各元素的和

    這篇文章主要為大家詳細介紹了C++實現求動態(tài)矩陣各元素的和,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • C++中字符串查找操作的兩則實例分享

    C++中字符串查找操作的兩則實例分享

    這篇文章主要介紹了C++中字符串的查找操作的兩則實例分享,分別是找到第一個只出現一次的字符以及找出連續(xù)最長的數字串的方法,需要的朋友可以參考下
    2016-02-02
  • OPENCV批量讀取圖片實現方法

    OPENCV批量讀取圖片實現方法

    下面小編就為大家?guī)硪黄狾PENCV批量讀取圖片實現方法。小編覺得挺不錯的?,F在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • opencv利用視頻的前n幀求平均圖像

    opencv利用視頻的前n幀求平均圖像

    這篇文章主要為大家詳細介紹了opencv利用視頻的前n幀求平均圖像,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C/C++中時間庫函數的使用詳解

    C/C++中時間庫函數的使用詳解

    這篇文章主要為大家詳細介紹了C/C++中的時間相關知識總結,例如時間庫函數的使用以及獲取本地時間的不同方法,文中的示例代碼講解詳細,需要的可以參考一下
    2022-11-11
  • Qt 使用 canon edsdk 實現實時預覽的示例代碼

    Qt 使用 canon edsdk 實現實時預覽的示例代碼

    這篇文章主要介紹了Qt 使用 canon edsdk 實現實時預覽的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-11-11

最新評論

长宁区| 本溪市| 县级市| 景宁| 周口市| 怀化市| 泰兴市| 电白县| 文安县| 东源县| 杭锦后旗| 监利县| 屏东县| 金沙县| 涪陵区| 滦南县| 永州市| 孟州市| 竹山县| 谷城县| 隆回县| 苍山县| 宁陵县| 雷波县| 诏安县| 安乡县| 长宁区| 库车县| 桐柏县| 山东| 广宁县| 高要市| 馆陶县| 宝兴县| 瑞金市| 新乐市| 夹江县| 巢湖市| 越西县| 阿克| 盈江县|