C++ OpenCV實戰(zhàn)之標(biāo)記點檢測的實現(xiàn)
在實際應(yīng)用中,能夠直接利用霍夫圓檢測這些理想方法的應(yīng)用場景是非常少的,更多的是利用擬合的辦法去尋找圓形。
大致思路如下,首先先選擇要處理的ROI部分,記錄下該圖的左上點在原圖的坐標(biāo),如果原圖過大,要先進行等比例縮放;然后利用自適應(yīng)閾值和Canny邊緣提取進行處理,再進行閉運算與輪廓檢測,計算點集面積,通過篩選面積閾值去除雜點,最后進行輪廓檢測,擬合橢圓,效果如下:
1.導(dǎo)入原圖:

2.截取ROI

3.進行自適應(yīng)閾值化與Canny邊緣提取

4.進行閉運算,然后輪廓檢測,然后計算點集面積,通過面積閾值去除雜點

5.再次進行輪廓檢測,擬合橢圓


代碼如下:
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\core\core.hpp>
#include <iostream>
#define scale 2//圖像縮放因子
#define cannythreshold 80
typedef struct _ROIStruct
{
cv::Point2d ROIPoint;
cv::Mat ROIImage;
}ROIStruct;
ROIStruct getROI(cv::Mat src,bool flag = false)
{
ROIStruct ROI_Struct;
cv::Rect2d ROIrect = selectROI(src);
ROI_Struct.ROIPoint = ROIrect.tl();//獲取ROI區(qū)域左上角的點
ROI_Struct.ROIImage = src(ROIrect);
if (flag == true)
{
cv::imshow("ROI", ROI_Struct.ROIImage);
}
return ROI_Struct;
}
int main()
{
cv::Mat srcImage = cv::imread("7.jpg");//讀取待處理的圖片
cv::resize(srcImage, srcImage, cv::Size(srcImage.cols / scale, srcImage.rows / scale));//圖像縮放,否則原來圖像會在ROI時顯示不下
ROIStruct ROI = getROI(srcImage);//選擇ROI區(qū)域
cv::Mat DetectImage, thresholdImage;
ROI.ROIImage.copyTo(DetectImage);
cv::imshow("ROI", DetectImage);
cv::cvtColor(DetectImage, thresholdImage, CV_RGB2GRAY);
cv::adaptiveThreshold(thresholdImage, thresholdImage, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY,11,35);//自適應(yīng)閾值
cv::Canny(thresholdImage, thresholdImage, cannythreshold, cannythreshold * 3, 3);
cv::imshow("thresholdImage", thresholdImage);
std::vector<std::vector<cv::Point>> contours1;
std::vector<cv::Vec4i> hierarchy1;
cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
cv::morphologyEx(thresholdImage, thresholdImage, cv::MORPH_CLOSE, element,cv::Point(-1,-1),2);
cv::Mat findImage = cv::Mat::zeros(thresholdImage.size(), CV_8UC3);
cv::findContours(thresholdImage, contours1, hierarchy1,CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
for (int i = 0; i <contours1.size();i++)
{
double area = cv::contourArea(contours1[i]);
//std::cout << i << "點集區(qū)域面積:" << area << std::endl;
if (area < 120)
{
continue;
}
else
{
drawContours(findImage, contours1, i, cv::Scalar(255, 255, 255), -1, 8, cv::Mat(), 0, cv::Point());
}
}
cv::imshow("drawing", findImage);
cv::Mat CircleImage(findImage.size(),CV_8UC1);
findImage.copyTo(CircleImage);
cv::cvtColor(CircleImage, CircleImage, CV_RGB2GRAY);
std::vector<std::vector<cv::Point>> contours2;
std::vector<cv::Vec4i> hierarchy2;
cv::Mat resultImage(CircleImage.size(), CV_8UC3);
cv::findContours(CircleImage, contours2, hierarchy2, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
std::vector<cv::Point> points1, points2;
cv::Mat compareImage;
DetectImage.copyTo(compareImage);
for (int j = 0; j <contours2.size();j++)
{
cv::RotatedRect box = cv::fitEllipse(contours2[j]);
points1.push_back(box.center);
ellipse(resultImage, box, cv::Scalar(0, 0, 255), 1, CV_AA);
ellipse(compareImage, box, cv::Scalar(0, 0, 255), 1, CV_AA);
}
for (int i = 0; i < points1.size(); i++)
{
cv::Point ans;
ans.x = ROI.ROIPoint.x + points1[i].x;
ans.x = ans.x*scale;
ans.y = ROI.ROIPoint.y + points1[i].y;
ans.y = ans.y*scale;
points2.push_back(ans);
}
std::cout << points1 << std::endl;
std::cout << ROI.ROIPoint << std::endl;
std::cout << points2 << std::endl;
cv::imshow("resultImage", resultImage);
cv::imshow("compareImage", compareImage);
cv::waitKey(0);
return 0;
}
到此這篇關(guān)于C++ OpenCV實戰(zhàn)之標(biāo)記點檢測的實現(xiàn)的文章就介紹到這了,更多相關(guān)C++ OpenCV標(biāo)記點檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何使用VSCode和CMake構(gòu)建跨平臺的C/C++開發(fā)環(huán)境
本文主要介紹了如何使用VSCode和CMake構(gòu)建跨平臺的C/C++開發(fā)環(huán)境,想進行跨平臺開發(fā)的同學(xué)們,一定要看一下2021-06-06
OpenCV圖像特征提取之Shi-Tomasi角點檢測算法詳解
Harris角點檢測算法就是對角點響應(yīng)函數(shù)R進行閾值處理,Shi-Tomasi原理幾乎和Harris一樣的,只不過最后計算角點響應(yīng)的公式發(fā)生了變化。本文將和大家詳細說說Shi-Tomasi角點檢測算法的原理與實現(xiàn),需要的可以參考一下2022-09-09

