網友提問—孔洞提取
最近有網友咨詢相關演算法問題,我給了一些幫助,覺得比較典型,在經過他允許后將相關資料和思路進行整理,放出來大家共同學習!
一、問題:
圖中這個孔是兩個半圓加直線組成的,不同于普通的圓和橢圓,所以用hough變換檢測效果不好,有沒有什么方法可以把那個孔的輪廓給提取出來?

二、分析和解體:
如果對hough的原理和使用比較了解的話(可以翻看《學習OpenCV》),就知道想利用houghcircle取出這樣的輪廓使不可能的,此類問題首先是要把關鍵區域強化出來,然后可以考慮輪廓分析的方法。
基于基礎演算法,做到目前程度。取這樣一個洞的影像,很容易被陰影干擾,需要在圖片采集的時候有所注意。
connection圖


所用gocvhelpe可以在我的github https://github.com/jsxyhelu 上找到,我的博客地址為jsxyhelu.cnblogs.com
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "GOCVHelper.h"
using namespace cv;
using namespace std;
using namespace GO;
RNG rng2(12345);
//根據輪廓的圓的特性進行選擇
vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue);
vector<VP> selectShapeCircularity(vector<VP> contours,float minvalue,float maxvalue);
//計算輪廓的圓的特性
float calculateCircularity(VP contour);
//根據輪廓的圓的特性進行選擇
vector<VP> selectShapeCircularity(Mat src,Mat& draw,vector<VP> contours,float minvalue,float maxvalue){
vector<VP> result_contours;
draw = Mat::zeros(src.rows,src.cols,CV_8UC3);
for (int i=0;i<contours.size();i++){
float fcompare = calculateCircularity(contours[i]);
if (fcompare >=minvalue && fcompare <=maxvalue)
result_contours.push_back(contours[i]);
}
for (int i=0;i<result_contours.size();i++){
Scalar color = Scalar(rng2.uniform(0,255),rng2.uniform(0,255),rng2.uniform(0,255));
drawContours(draw,result_contours,i,color,-1);
}
return result_contours;
}
vector<VP> selectShapeCircularity(vector<VP> contours,float minvalue,float maxvalue){
vector<VP> result_contours;
for (int i=0;i<contours.size();i++){
float fcompare = calculateCircularity(contours[i]);
if (fcompare >=minvalue && fcompare <=maxvalue)
result_contours.push_back(contours[i]);
}
return result_contours;
}
//計算輪廓的圓的特性
float calculateCircularity(VP contour){
Point2f center;
float radius = 0;
minEnclosingCircle((Mat)contour,center,radius);
//以最小外接圓半徑作為數學期望,計算輪廓上各點到圓心距離的標準差
float fsum = 0;
float fcompare = 0;
for (int i=0;i<contour.size();i++){
Point2f ptmp = contour[i];
float fdistenct = sqrt((float)((ptmp.x - center.x)*(ptmp.x - center.x)+(ptmp.y - center.y)*(ptmp.y-center.y)));
float fdiff = abs(fdistenct - radius);
fsum = fsum + fdiff;
}
fcompare = fsum/(float)contour.size();
return fcompare;
}
int _tmain(int argc, _TCHAR* argv[])
{
//讀入灰度的手部影像
Mat src = imread("e:/sandbox/kong.jpg");
Mat dst = src.clone();
Mat tmp;
Mat draw;
vector<VP> contours;
vector<VP> results;
vector<Mat> planes;
cvtColor(src,src,COLOR_BGR2HSV);
split(src,planes);
//v通道
tmp = planes[2].clone();
//去除毛刺
GaussianBlur(tmp,tmp,Size(3,3),0);
//閾值處理
threshold(tmp,tmp,100,255,THRESH_OTSU);
//反向
bitwise_not(tmp,tmp);
//形態學
erode(tmp,tmp,Mat());
dilate(tmp,tmp,Mat());
//繪制聯通區域
contours = GO::connection2(tmp,draw);
//輪廓分析(圓特性)
results = selectShapeCircularity(tmp,draw,contours, 100,500);
//原圖繪制
drawContours(dst,results,0,Scalar(0,0,255),3);
imshow("result",dst);
waitKey();
return 0;
}
uj5u.com熱心網友回復:
搜“”halcon“”?uj5u.com熱心網友回復:
紅外相機看看照片效果,這樣子很難提取uj5u.com熱心網友回復:
你可以進行一次灰度化,然后進行二值化,然后做適當的膨脹,再做一次腐蝕,然后,用canny邊緣提取或者sobel邊緣提取或者對膨脹和腐蝕的二值圖進行一個差值,差不多能出來一個大概的邊緣
uj5u.com熱心網友回復:
https://docs.opencv.org/3.4.0/d4/dc6/tutorial_py_template_matching.htmluj5u.com熱心網友回復:
搜“”halcon“”!!!!uj5u.com熱心網友回復:
這么多年來, 趙4老師在論壇灌水, 淹死了pig884,又淹死了"娜姐", 是為啥呢?
uj5u.com熱心網友回復:
我灌故我在。
uj5u.com熱心網友回復:
https://docs.opencv.org/3.4.0/d4/dc6/tutorial_py_template_matching.html
這么多年來, 趙4老師在論壇灌水, 淹死了pig884,又淹死了"娜姐", 是為啥呢?
我灌故我在。
經過大資料分析, 趙4老師是一個自由職業者, 平常以接軟體外包為主, 外包專案來源主要是從各論壇留言聯系, 以及熟人介紹
uj5u.com熱心網友回復:
學習~
uj5u.com熱心網友回復:
https://docs.opencv.org/3.4.0/d4/dc6/tutorial_py_template_matching.html
這么多年來, 趙4老師在論壇灌水, 淹死了pig884,又淹死了"娜姐", 是為啥呢?
我灌故我在。
經過大資料分析, 趙4老師是一個自由職業者, 平常以接軟體外包為主, 外包專案來源主要是從各論壇留言聯系, 以及熟人介紹
要靠這個吃飯的話,我早餓死了!
uj5u.com熱心網友回復:
拋磚引玉,只是提供一個思路。轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/72213.html
標籤:圖形處理/算法
上一篇:邊緣檢測之后的影像處理
