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

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

 更新時間:2021年11月30日 08:38:38   作者:翟天保Steven  
在對圖像進(jìn)行處理時,經(jīng)常會要提取出圖像中某條直線、圓線或者ROI區(qū)域內(nèi)的感興趣數(shù)據(jù),進(jìn)行重點(diǎn)關(guān)注。本文主要介紹了利用OpenCV獲取圖像中圓線上的數(shù)據(jù),需要的可以參考一下

需求說明

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

直線的提取見:

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

而圓線的提取則是本文要將的內(nèi)容,對圓線而言,將線上某點(diǎn)作為起點(diǎn),沿順時針或逆時針方向依次提取感興趣數(shù)據(jù),可放置在容器中。那么如何快速提取呢?本文提供了一種比較簡單的思路,應(yīng)用窗口模板,在窗口中快速找到下一可前進(jìn)點(diǎn)的位置,步進(jìn)然后再找下個點(diǎn),形成路徑追蹤,進(jìn)而實(shí)現(xiàn)整圈圓線數(shù)據(jù)的提取。

具體流程

1)初始化。設(shè)置路徑追蹤窗口尺寸size為3,創(chuàng)建path作為行進(jìn)路徑,p點(diǎn)作為起點(diǎn),c用來存放目標(biāo)數(shù)據(jù)點(diǎn)。

cv::Mat c;
int size = 3;
cv::Mat path = mask.clone();
Point p = Point(center.x + radius, center.y);

2)將起點(diǎn)放置在c中,將path中的起點(diǎn)值置0,表示該點(diǎn)已經(jīng)走過。

c.push_back(src.at<uchar>(p.y, p.x));
path.at<uchar>(p.y, p.x) = 0;

3)用WinDataNum函數(shù)判斷當(dāng)前點(diǎn)的窗口內(nèi)有幾個可前進(jìn)點(diǎn),若無則說明路徑封死或者完成路徑,wn值表示可前進(jìn)點(diǎn)的個數(shù)。

int wn = WinDataNum(path, p, size);

4)窗口內(nèi)遍歷,查看是否有可前進(jìn)路徑,若找到,則將當(dāng)前點(diǎn)信息刷新為此點(diǎn),并將標(biāo)記符find設(shè)為true,find的意義是快速中斷遍歷,用來提速。

int t = size / 2;
bool find = false;
for (int i = p.y - t; i <= p.y + t; ++i)
{
	uchar *g = path.ptr<uchar>(i);
	for (int j = p.x - t; j <= p.x + t; ++j)
	{
		if (g[j] == 255)
		{
			p.x = j;
			p.y = i;
			find = true;
			break;
		}
	}
	if (find)
		break;
}

5)若找到了點(diǎn),即find為true,則將該點(diǎn)的數(shù)據(jù)存放在c中,path中置0,并以該點(diǎn)為中心搜索窗口內(nèi)可前進(jìn)路徑。

if (find)
{
	c.push_back(src.at<uchar>(p.y, p.x));
	path.at<uchar>(p.y, p.x) = 0;
	wn = WinDataNum(path, p, size);
}
else
	break;

6)若wn為0了,則說明路徑封死或者完成路徑了,跳出循環(huán),函數(shù)執(zhí)行完畢。?

while (wn)
{
	int t = size / 2;
	bool find = false;
	for (int i = p.y - t; i <= p.y + t; ++i)
	{
		uchar *g = path.ptr<uchar>(i);
		for (int j = p.x - t; j <= p.x + t; ++j)
		{
			if (g[j] == 255)
			{
				p.x = j;
				p.y = i;
				find = true;
				break;
			}
		}
		if (find)
			break;
	}
	if (find)
	{
		c.push_back(src.at<uchar>(p.y, p.x));
		path.at<uchar>(p.y, p.x) = 0;
		wn = WinDataNum(path, p, size);
	}
	else
		break;
 
}

功能函數(shù)

// 獲取圓圈上的數(shù)據(jù),逆時針存儲,起點(diǎn)在中心同行最右側(cè)數(shù)據(jù)
cv::Mat getCircleData(cv::Mat src, cv::Mat mask, cv::Point center, int radius)
{
	cv::Mat c;
	int size = 3;
	cv::Mat path = mask.clone();
	Point p = Point(center.x + radius, center.y);
	c.push_back(src.at<uchar>(p.y, p.x));
	path.at<uchar>(p.y, p.x) = 0;
	int wn = WinDataNum(path, p, size);
	while (wn)
	{
		int t = size / 2;
		bool find = false;
		for (int i = p.y - t; i <= p.y + t; ++i)
		{
			uchar *g = path.ptr<uchar>(i);
			for (int j = p.x - t; j <= p.x + t; ++j)
			{
				if (g[j] == 255)
				{
					p.x = j;
					p.y = i;
					find = true;
					break;
				}
			}
			if (find)
				break;
		}
		if (find)
		{
			c.push_back(src.at<uchar>(p.y, p.x));
			path.at<uchar>(p.y, p.x) = 0;
			wn = WinDataNum(path, p, size);
		}
		else
			break;
 
	}
	return c;
}
// 獲取窗口內(nèi)的有效數(shù)據(jù)個數(shù)
int WinDataNum(cv::Mat path, cv::Point p, int size)
{
	int number = 0;
	int t = size / 2;
	for (int i = p.y - t; i <= p.y + t; ++i)
	{
		uchar *g = path.ptr<uchar>(i);
		for (int j = p.x - t; j <= p.x + t; ++j)
		{
			if (g[j] == 255)
				number++;
		}
	}
	return number;
}

C++測試代碼

#include <iostream>
#include <opencv2/opencv.hpp>
#include <string>
 
using namespace std;
using namespace cv;
 
cv::Mat getCircleData(cv::Mat src, cv::Mat mask, cv::Point center, int radius);
int WinDataNum(cv::Mat path, cv::Point p, int size);
 
int main()
{
	cv::Mat src = imread("test.jpg", 0);
	cv::Mat mask = cv::Mat::zeros(src.size(), CV_8UC1);
	cv::Point center = cv::Point(src.cols / 2, src.rows / 2);
	int radius = min(src.cols, src.rows) / 2 - 10;
	circle(mask, center, radius, Scalar(255), 1, 8);
	cv::Mat c = getCircleData(src, mask, center, radius);
	src.setTo(0, mask == 0);
	imshow("src", src);
	imshow("mask", mask);
	waitKey(0);
 
	return 0;
}
 
// 獲取圓圈上的數(shù)據(jù),逆時針存儲,起點(diǎn)在中心同行最右側(cè)數(shù)據(jù)
cv::Mat getCircleData(cv::Mat src, cv::Mat mask, cv::Point center, int radius)
{
	cv::Mat c;
	int size = 3;
	cv::Mat path = mask.clone();
	Point p = Point(center.x + radius, center.y);
	c.push_back(src.at<uchar>(p.y, p.x));
	path.at<uchar>(p.y, p.x) = 0;
	int wn = WinDataNum(path, p, size);
	while (wn)
	{
		int t = size / 2;
		bool find = false;
		for (int i = p.y - t; i <= p.y + t; ++i)
		{
			uchar *g = path.ptr<uchar>(i);
			for (int j = p.x - t; j <= p.x + t; ++j)
			{
				if (g[j] == 255)
				{
					p.x = j;
					p.y = i;
					find = true;
					break;
				}
			}
			if (find)
				break;
		}
		if (find)
		{
			c.push_back(src.at<uchar>(p.y, p.x));
			path.at<uchar>(p.y, p.x) = 0;
			wn = WinDataNum(path, p, size);
		}
		else
			break;
 
	}
	return c;
}
 
// 獲取窗口內(nèi)的有效數(shù)據(jù)個數(shù)
int WinDataNum(cv::Mat path, cv::Point p, int size)
{
	int number = 0;
	int t = size / 2;
	for (int i = p.y - t; i <= p.y + t; ++i)
	{
		uchar *g = path.ptr<uchar>(i);
		for (int j = p.x - t; j <= p.x + t; ++j)
		{
			if (g[j] == 255)
				number++;
		}
	}
	return number;
}

測試效果

圖1 原圖

圖2 掩膜內(nèi)圖像

如圖1圖2所示,掩膜內(nèi)的圖像數(shù)據(jù)就是我們要提取的目標(biāo)。

圖3 放大后數(shù)據(jù)搜索路徑

圖3放大后可以看出,起點(diǎn)是230,之后的數(shù)據(jù)是230、231、236、232、234、146等等,再看c容器中的數(shù)據(jù)。

圖4 容器內(nèi)數(shù)據(jù)

對比完開頭,再看結(jié)尾,如圖3所示,是234、234、231、234、234,然后就是起點(diǎn)230,查看容器。

圖5 容器內(nèi)數(shù)據(jù)

這樣有的小伙伴可能覺得中間會不會有數(shù)據(jù)錯誤呢,很簡單,打開VS復(fù)制代碼后,搭配ImageWatch插件,debug調(diào)試打斷點(diǎn)觀察path矩陣,看看它的255數(shù)據(jù)是不是按預(yù)想的路徑消失,如果是則說明扔的數(shù)據(jù)也沒有問題。

總結(jié)

本文提供的只是一個簡單思路,有一定局限性。比如該方法在圓線寬為1時效果最佳,若線寬大了就不能用窗口簡單判斷了;另外,起點(diǎn)在右側(cè)時是逆時針獲取數(shù)據(jù),起點(diǎn)在左側(cè)時是順時針獲取數(shù)據(jù),如果想統(tǒng)一標(biāo)準(zhǔn)的話,最好加上起點(diǎn)的位置判斷,然后決定是否將c的數(shù)據(jù)翻轉(zhuǎn)。至于運(yùn)行速度方面,3000*3000的圖像矩陣中運(yùn)行基本為0ms,畢竟只是提取了一條圓線而已。

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

相關(guān)文章

  • C/C++: Inline function, calloc 對比 malloc

    C/C++: Inline function, calloc 對比 malloc

    以下是對c/c++中的malloc函數(shù)與calloc函數(shù)的區(qū)別以及它們之間的聯(lián)系進(jìn)行了介紹,需要的朋友可以過來參考下
    2016-07-07
  • C語言實(shí)現(xiàn)兩個矩陣相乘

    C語言實(shí)現(xiàn)兩個矩陣相乘

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)兩個矩陣相乘的程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • C語言實(shí)現(xiàn)簡單的通訊錄管理系統(tǒng)

    C語言實(shí)現(xiàn)簡單的通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言用fstat函數(shù)獲取文件的大小方法

    C語言用fstat函數(shù)獲取文件的大小方法

    今天小編就為大家分享一篇關(guān)于C語言用fstat函數(shù)獲取文件的大小方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • MFC實(shí)現(xiàn)漂亮界面之美化按鈕

    MFC實(shí)現(xiàn)漂亮界面之美化按鈕

    這篇文章主要為大家詳細(xì)介紹了MFC實(shí)現(xiàn)漂亮界面之美化按鈕,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C++實(shí)現(xiàn)簡單推箱子小游戲

    C++實(shí)現(xiàn)簡單推箱子小游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡單推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08
  • C++中std::thread線程用法

    C++中std::thread線程用法

    本文主要介紹了C++中std::thread線程用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • C語言實(shí)現(xiàn)六邊形掃雷游戲的示例代碼

    C語言實(shí)現(xiàn)六邊形掃雷游戲的示例代碼

    所謂六邊形掃雷,就是沒有掃雷模式的消零算法,每一個安全的點(diǎn)都需要單獨(dú)挖出來,一次顯示一個格子,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-12-12
  • C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    C++超詳細(xì)實(shí)現(xiàn)堆和堆排序過像

    堆是計(jì)算機(jī)科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個可以被看做一棵完全二叉樹的數(shù)組對象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。本文將通過圖片詳細(xì)介紹堆排序,需要的可以參考一下
    2022-06-06
  • QT自定義之滑動開關(guān)

    QT自定義之滑動開關(guān)

    這篇文章主要為大家詳細(xì)介紹了QT自定義之滑動開關(guān)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-08-08

最新評論

万安县| 安义县| 宝清县| 黎城县| 赞皇县| 汝南县| 宜丰县| 岳西县| 星座| 郑州市| 上饶市| 迁安市| 当阳市| 雅安市| 依兰县| 新安县| 兰溪市| 独山县| 台州市| 噶尔县| 麻阳| 来安县| 湘西| 淅川县| 卫辉市| 察隅县| 兴山县| 望都县| 梅河口市| 南投市| 汝城县| 平舆县| 平湖市| 政和县| 杂多县| 太保市| 宿迁市| 松潘县| 芦溪县| 兰西县| 宽城|