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

服務器之家:專注于服務器技術及軟件下載分享
分類導航

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

服務器之家 - 編程語言 - C/C++ - OpenCV提取圖像中圓線上的數據具體流程

OpenCV提取圖像中圓線上的數據具體流程

2022-03-07 14:29翟天保Steven C/C++

在對圖像進行處理時,經常會要提取出圖像中某條直線、圓線或者ROI區域內的感興趣數據,進行重點關注。本文主要介紹了利用OpenCV獲取圖像中圓線上的數據,需要的可以參考一下

需求說明

在對圖像進行處理時,經常會有這類需求:客戶想要提取出圖像中某條直線、圓線或者ROI區域內的感興趣數據,進行重點關注。該需求在圖像檢測領域尤其常見。ROI區域一般搭配Rect即可完成提取,直線和圓線數據的提取沒有現成的函數,需要自行實現。

直線的提取見:

OpenCV獲取圖像中直線上的數據具體流程

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

 

具體流程

1)初始化。設置路徑追蹤窗口尺寸size為3,創建path作為行進路徑,p點作為起點,c用來存放目標數據點。

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

2)將起點放置在c中,將path中的起點值置0,表示該點已經走過。

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

3)用WinDataNum函數判斷當前點的窗口內有幾個可前進點,若無則說明路徑封死或者完成路徑,wn值表示可前進點的個數。

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

4)窗口內遍歷,查看是否有可前進路徑,若找到,則將當前點信息刷新為此點,并將標記符find設為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)若找到了點,即find為true,則將該點的數據存放在c中,path中置0,并以該點為中心搜索窗口內可前進路徑。

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了,則說明路徑封死或者完成路徑了,跳出循環,函數執行完畢。 

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;

}

 

功能函數

// 獲取圓圈上的數據,逆時針存儲,起點在中心同行最右側數據
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;
}
// 獲取窗口內的有效數據個數
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;
}

// 獲取圓圈上的數據,逆時針存儲,起點在中心同行最右側數據
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;
}

// 獲取窗口內的有效數據個數
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;
}

 

測試效果

OpenCV提取圖像中圓線上的數據具體流程

圖1 原圖

OpenCV提取圖像中圓線上的數據具體流程

圖2 掩膜內圖像

如圖1圖2所示,掩膜內的圖像數據就是我們要提取的目標。

OpenCV提取圖像中圓線上的數據具體流程

圖3 放大后數據搜索路徑

圖3放大后可以看出,起點是230,之后的數據是230、231、236、232、234、146等等,再看c容器中的數據。

OpenCV提取圖像中圓線上的數據具體流程

圖4 容器內數據

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

OpenCV提取圖像中圓線上的數據具體流程

圖5 容器內數據

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

 

總結

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

到此這篇關于OpenCV提取圖像中圓線上的數據具體流程的文章就介紹到這了,更多相關OpenCV提取圖像數據內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

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

延伸 · 閱讀

精彩推薦
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
主站蜘蛛池模板: 日韩成人| 国产精品久久久久久久久久久久 | 亚洲a人 | 白浆在线| jdav视频在线观看免费 | 91久久极品| 国产黄色免费观看 | 中文字幕国产日韩 | 91亚洲国产成人久久精品网站 | av手机在线电影 | 丁香婷婷综合激情五月色 | 亚洲精品成人在线 | 都市激情av | 高清18麻豆 | 粉嫩一区二区三区 | 香蕉av777xxx色综合一区 | 青青在线精品视频 | 久久亚洲一区二区 | 日日日操| 成人网av| 亚洲精品一区二区三区精华液 | 91电影在线 | 蜜桃av噜噜一区二区三区小说 | 午夜在线视频播放 | 一区二区三区在线播放 | 操操日日| 久久高清精品 | 夜夜爽av福利精品导航 | 污视频免费网站 | 亚洲精品影院 | 欧美视频区 | 日韩理伦片在线观看视频播放 | 久色成人| 精品婷婷 | 久久国产精品久久喷水 | 亚洲三级视频 | 国产美女视频自拍 | 欧美日韩综合 | 在线91视频 | 免费av电影网站 | 久操成人|