国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - C/C++ - OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程

OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程

2022-02-20 14:32翟天保Steven C/C++

對(duì)圖像進(jìn)行處理時(shí),經(jīng)常會(huì)有這類需求:客戶想要提取出圖像中某條直線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點(diǎn)關(guān)注,怎么操作呢,下面小編通過實(shí)例代碼介紹下OpenCV獲取圖像中直線上的數(shù)據(jù),一起看看吧

需求說明

在對(duì)圖像進(jìn)行處理時(shí),經(jīng)常會(huì)有這類需求:客戶想要提取出圖像中某條直線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點(diǎn)關(guān)注。該需求在圖像檢測(cè)領(lǐng)域尤其常見。ROI區(qū)域一般搭配Rect即可完成提取,直線數(shù)據(jù)的提取沒有現(xiàn)成的函數(shù),需要自行實(shí)現(xiàn)。

當(dāng)直線為縱向或者橫向時(shí),比較簡(jiǎn)單,只需要從起點(diǎn)到終點(diǎn)提取該行或者列的數(shù)據(jù)即可;但是直線若為斜向的,則需要從起點(diǎn)出發(fā),向終點(diǎn)方向逐個(gè)像素提取。大家都知道,圖像是由許多像素組成,而斜向直線的數(shù)據(jù)提取路線并不一定就是標(biāo)準(zhǔn)的斜線,也可能是呈階梯狀的路線,而如何進(jìn)行路線設(shè)計(jì),就是本文所要展示的內(nèi)容。

 

具體流程

1)建立vector<pair<float,int>> result容器用于存放數(shù)據(jù),設(shè)置初始化參數(shù)。其中,inImage是輸入圖像,start為起點(diǎn),end為終點(diǎn),點(diǎn)的類型為cv::Point。

vector<pair<float, int>> result;
int row = inImage.rows;
int col = inImage.cols;
int r1 = start.y;
int c1 = start.x;
int r2 = end.y;
int c2 = end.x;

2)確定兩點(diǎn)間距離dist,將起點(diǎn)到終點(diǎn)的橫坐標(biāo)差和縱坐標(biāo)差進(jìn)行勾股定理可得。所得距離可能為帶小數(shù)的數(shù)據(jù),然而像素的個(gè)數(shù)都為整數(shù),所以進(jìn)行四舍五入。除此之外,還要判斷下距離,若距離為0,則只返回起點(diǎn)數(shù)據(jù)。

float dist = round(sqrt(pow(float(r2) - float(r1), 2.0) + pow(float(c2) - float(c1), 2.0)));
if (dist <= 0.00001f) {
	pair<float, int> temp;
	temp.first = inImage.at<float>(r1, c1);
	temp.second = 0;
	result.push_back(temp);
	return result;
}

3)確定橫向縱向的步進(jìn)間隔。

float slope_r = (float(r2) - float(r1)) / dist;
float slope_c = (float(c2) - float(c1)) / dist;

4)建立Flag地圖,用于標(biāo)記已存儲(chǔ)過的位置,避免同一數(shù)據(jù)二次放入。

cv::Mat Flag = cv::Mat::zeros(mask.size(), mask.type());

5)開始存儲(chǔ)數(shù)據(jù)。計(jì)數(shù)從0開始,若該點(diǎn)處于掩膜內(nèi),且Flag地圖中沒有標(biāo)記,則進(jìn)行存儲(chǔ)。

int k = 0;
for (float i = 0; i <= dist; ++i) {
	// 若該點(diǎn)處于掩膜內(nèi),且未被Flag存儲(chǔ),則進(jìn)行存儲(chǔ)工作
	if ((mask.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 255)
		&& (Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 0))
	{
		pair<float, int> temp;
		temp.first = inImage.at<float>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c)));
		temp.second = k;
		Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) = 255;
		k++;
		result.push_back(temp);
	}
}

功能函數(shù)

/**
* @brief GetOneDimLineData                 獲取一維直線數(shù)據(jù)
* @param inImage                           輸入位相圖
* @param mask                              輸入掩膜圖
* @param start                             起始點(diǎn)坐標(biāo)
* @param end                               終點(diǎn)坐標(biāo)
* @return                                  直線數(shù)據(jù)(數(shù)值&序號(hào))
*/
vector<pair<float, int>> GetOneDimLineData(const cv::Mat inImage, cv::Mat mask, cv::Point start, cv::Point end)
{
	vector<pair<float, int>> result;
	int row = inImage.rows;
	int col = inImage.cols;
	int r1 = start.y;
	int c1 = start.x;
	int r2 = end.y;
	int c2 = end.x;
	// 確定兩點(diǎn)間距離
	float dist = round(sqrt(pow(float(r2) - float(r1), 2.0) + pow(float(c2) - float(c1), 2.0)));
	if (dist <= 0.00001f) {
		pair<float, int> temp;
		temp.first = inImage.at<float>(r1, c1);
		temp.second = 0;
		result.push_back(temp);
		return result;
	}
	// 橫向縱向的步進(jìn)間隔
	float slope_r = (float(r2) - float(r1)) / dist;
	float slope_c = (float(c2) - float(c1)) / dist;
	// Flag地圖,用于存儲(chǔ)已放入的數(shù)據(jù),避免同一數(shù)據(jù)二次放入
	cv::Mat Flag = cv::Mat::zeros(mask.size(), mask.type());
	// 數(shù)據(jù)量計(jì)數(shù),從0開始
	int k = 0;
	for (float i = 0; i <= dist; ++i) {
		// 若該點(diǎn)處于掩膜內(nèi),且未被Flag存儲(chǔ),則進(jìn)行存儲(chǔ)工作
		if ((mask.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 255)
			&& (Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 0))
		{
			pair<float, int> temp;
			temp.first = inImage.at<float>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c)));
			temp.second = k;
			Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) = 255;
			k++;
			result.push_back(temp);
		}
	}
	return result;
}

C++測(cè)試代碼

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>

using namespace std;
using namespace cv;

vector<pair<float, int>> GetOneDimLineData(const cv::Mat inImage, cv::Mat mask, cv::Point start, cv::Point end);

int main()
{
	Mat src(10,10,CV_32FC1,nan(""));
	for (int i = 3; i < 7; ++i)
	{
		for (int j = 3; j < 9; ++j)
		{
			src.at<float>(i, j) = rand() % 255;
		}
	}
	cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);
	mask.setTo(255, src == src);
	Point start = Point(2, 1);
	Point end = Point(8, 7);
	vector<pair<float, int>> test= GetOneDimLineData(src,mask, start, end);
	cout << "size:" << test.size() << endl;
	for (int i=0;i<test.size();++i)
	{
		cout << i << ":" << endl;
		cout << test[i].first << " " << test[i].second << endl;
	}
	return 0;
}

/**
* @brief GetOneDimLineData                 獲取一維直線數(shù)據(jù)
* @param inImage                           輸入位相圖
* @param mask                              輸入掩膜圖
* @param start                             起始點(diǎn)坐標(biāo)
* @param end                               終點(diǎn)坐標(biāo)
* @return                                  直線數(shù)據(jù)(數(shù)值&序號(hào))
*/
vector<pair<float, int>> GetOneDimLineData(const cv::Mat inImage, cv::Mat mask, cv::Point start, cv::Point end)
{
	vector<pair<float, int>> result;
	int row = inImage.rows;
	int col = inImage.cols;
	int r1 = start.y;
	int c1 = start.x;
	int r2 = end.y;
	int c2 = end.x;
	// 確定兩點(diǎn)間距離
	float dist = round(sqrt(pow(float(r2) - float(r1), 2.0) + pow(float(c2) - float(c1), 2.0)));
	if (dist <= 0.00001f) {
		pair<float, int> temp;
		temp.first = inImage.at<float>(r1, c1);
		temp.second = 0;
		result.push_back(temp);
		return result;
	}
	// 橫向縱向的步進(jìn)間隔
	float slope_r = (float(r2) - float(r1)) / dist;
	float slope_c = (float(c2) - float(c1)) / dist;
	// Flag地圖,用于存儲(chǔ)已放入的數(shù)據(jù),避免同一數(shù)據(jù)二次放入
	cv::Mat Flag = cv::Mat::zeros(mask.size(), mask.type());
	// 數(shù)據(jù)量計(jì)數(shù),從0開始
	int k = 0;
	for (float i = 0; i <= dist; ++i) {
		// 若該點(diǎn)處于掩膜內(nèi),且未被Flag存儲(chǔ),則進(jìn)行存儲(chǔ)工作
		if ((mask.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 255)
			&& (Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) == 0))
		{
			pair<float, int> temp;
			temp.first = inImage.at<float>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c)));
			temp.second = k;
			Flag.at<uchar>(int(r1) + int(round(i * slope_r)), int(c1) + int(round(i * slope_c))) = 255;
			k++;
			result.push_back(temp);
		}
	}
	return result;
}

測(cè)試效果

OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程

 

圖1 初始化測(cè)試圖像

 

OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程

 

圖2 Flag地圖

 

OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程

 

圖3 結(jié)果打印

 

不難看出,獲取的數(shù)據(jù)為直線上數(shù)據(jù)。對(duì)于有一定斜度的直線,F(xiàn)lag地圖可能呈現(xiàn)階梯狀步進(jìn)路線,這也是正常的~

如果函數(shù)有什么可以改進(jìn)完善的地方,非常歡迎大家指出,一同進(jìn)步何樂而不為呢~

到此這篇關(guān)于OpenCV獲取圖像中直線上的數(shù)據(jù)具體流程的文章就介紹到這了,更多相關(guān)OpenCV獲取圖像數(shù)據(jù)內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/zhaitianbao/article/details/121113525

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美高清在线 | 最新中文字幕在线 | 中文字幕日韩一区 | 精品在线一区二区 | 欧美日韩亚洲视频 | 国产精品视频导航 | 亚洲精品一区二区三区在线 | 中文字幕日韩欧美 | 欧美综合色 | 国产精品国产a级 | 龙珠z国语291集普通话 | 日韩精品专区 | 美色阁av | av色伊人久久综合一区二区 | 中文字幕av一区二区三区 | 成人欧美一区二区三区在线播放 | 成人爱情偷拍视频在线观看 | 精品久久久久久久久久久下田 | 在线精品一区 | 日韩欧美一区二区三区免费观看 | 亚洲人成免费网站 | 国产精品久久久久久久久久免费 | 国产欧美高清在线观看 | 中文字幕国产一区 | 自拍在线 | 欧美成年黄网站色视频 | 久久久久国产一区二区三区 | 日本视频一区二区 | 久久精品日韩 | 国产一区二区三区午夜 | 国产成人99久久亚洲综合精品 | 成人精品一区二区 | 国产欧美日韩综合精品一区二区 | 理论电影在线 | 久久久91 | 亚洲精品日本 | 毛片视频免费 | 天天操天天干天天爽 | 伊人久久精品久久亚洲一区 | av免费资源 | 日韩三级电影网 |