摘要
這套算法首先解決了在復雜背景下輪廓提取的問題,而且我認為也是穩健魯棒的。其中,算法中除了經典的“hsv分解->ostu閾值->最大輪廓標注”外,最為關鍵的算法為底帽去光差。這個算法來自於岡薩雷斯《數字圖像處理教程》形態學篇章,完全按照書本建議實現,體現良好作用。
一、問題提出
這是一個來自"answerOpenCV"(http://answers.opencv.org/question/200422/opencv-c-filling-holes/)整編如下:
content:
Hello there,
For a personnel projet, I'm trying to detect object and there shadow. These are the result I have for now: Original:
二、問題分析
從原始圖片上來看,這張圖片的拍攝的背景比較復雜,此外光照也存在偏光現象;而提問者雖然提出的是“將縫隙合並”的要求,實際上他還是想得到目標物體的准確輪廓。
整體思路:(思路很重要!!!)
- 讀入圖像,轉成hsv空間
- 對h通道圖像底帽運算
- 二值化
- 尋找輪廓,並篩選顯示
opencv實現:
Mat moveLightDiff(Mat src, int radius); Mat src = imread("D:/opencv練習圖片/復雜背景下提取輪廓.png"); imshow("原始圖", src); Mat src_hsv,src_h,src_s, src_v,src_tophat,src_bin; cvtColor(src, src_hsv, COLOR_RGB2HSV); vector<Mat> rgb_planes; split(src_hsv, rgb_planes); src_h = rgb_planes[0]; imshow("H通道", src_h); Mat kernel = getStructuringElement(MORPH_RECT, Size(30, 30), Point(-1, -1)); morphologyEx(src_h, src_h, MORPH_BLACKHAT, kernel, Point(-1, -1)); imshow("BLACKPHAT", src_h); threshold(src_h, src_bin, 100, 255, THRESH_OTSU); imshow("二值化", src_bin); int max = 0; int index = -1; vector<vector<Point> >contours; findContours(src_bin, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); for (int i = 0; i < contours.size(); i++) { int area= contourArea(contours[i]); if (max < area) { index = i; max = area; } } drawContours(src, contours, index, Scalar(0, 0, 255), 2); imshow("顯示輪廓", src);
頂帽運算與底帽運算的理解和分析
頂帽變換和底帽(黑帽)變換屬於圖像形態學處理的一種,可用於校正不均勻光照的影響。
- 頂帽變換用於凸顯暗背景上的亮物體。(也可叫白帽)
- 底帽變換用於凸顯亮背景上的暗物體。(也可叫黑帽)
如上圖所示。當圖像各部分光照不均勻造成的背景灰度不均現象,單純用二值化處理效果不好就可以用頂帽(底帽)處理。由於原圖是背景亮,前景暗,對原圖進行底帽變換以解決光照不均勻的問題。
直接對h通道二值化效果:
先底帽矯正后再二值化效果:
摘錄於尋找復雜背景下物體的輪廓(OpenCV / C++ - Filling holes) - jsxyhelu - 博客園 (cnblogs.com)