OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域

OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域

 OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域

   【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78142749
   之前本博客在Matlab实现了《Matlab形态学图像处理:二值图像分割 标记连通区域和重心位置 删除连通区域》http://blog.csdn.net/guyuealian/article/details/71440949,现在本人使用OpenCV实现这一功能:对图像进行二值化分割,并用“红色矩形”标记连通区域的面积,为了减少噪声的干扰,删除面积小的区域,代码中将连通区域面积(像素个数)不足100的区域认为是噪声点,并将其删除(即置为背景黑色)。本人制作了一个GIF动画图,以便大家观看效果图:

OpenCV参考代码如下:

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2. #include <iostream>    
  3. #include<vector>  
  4. #include<algorithm>  
  5. #include <opencv2\opencv.hpp>    
  6. #include <opencv2\highgui\highgui.hpp>    
  7. using namespace std;  
  8. using namespace cv;  
  9.   
  10.   
  11. //轮廓按照面积大小升序排序  
  12. bool ascendSort(vector<Point> a, vector<Point> b) {  
  13.     return a.size() < b.size();  
  14.   
  15. }  
  16.   
  17. //轮廓按照面积大小降序排序  
  18. bool descendSort(vector<Point> a, vector<Point> b) {  
  19.     return a.size() > b.size();  
  20. }  
  21. int main() {  
  22.     Mat srcImage = imread("D:\\OpencvTest\\123.jpg");  
  23.     Mat thresholdImage;  
  24.     Mat grayImage;  
  25.     cvtColor(srcImage, grayImage, CV_BGR2GRAY);  
  26.     threshold(grayImage, thresholdImage, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);  
  27.     //Mat resultImage;  
  28.     //thresholdImage.copyTo(resultImage);  
  29.     vector< vector< Point> > contours;  //用于保存所有轮廓信息  
  30.     vector< vector< Point> > contours2; //用于保存面积不足100的轮廓  
  31.     vector<Point> tempV;              //暂存的轮廓  
  32.   
  33.     findContours(thresholdImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);  
  34.     //cv::Mat labels;  
  35.     //int N = connectedComponents(resultImage, labels, 8, CV_16U);  
  36.     //findContours(labels, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);  
  37.   
  38.     //轮廓按照面积大小进行升序排序  
  39.     sort(contours.begin(), contours.end(), ascendSort);//升序排序  
  40.     vector<vector<Point> >::iterator itc = contours.begin();  
  41.     int i = 0;  
  42.     while (itc != contours.end())  
  43.     {  
  44.         //获得轮廓的矩形边界  
  45.         Rect rect = boundingRect(*itc);  
  46.         int x = rect.x;  
  47.         int y = rect.y;  
  48.         int w = rect.width;  
  49.         int h = rect.height;  
  50.         //绘制轮廓的矩形边界  
  51.         cv::rectangle(srcImage, rect, { 0, 0, 255 }, 1);  
  52.         //保存图片  
  53.         char str[10];  
  54.         sprintf(str, "%d.jpg", i++);  
  55.         cv::imshow("srcImage", srcImage);  
  56.         imwrite(str, srcImage);  
  57.         waitKey(1000);  
  58.       
  59.         if (itc->size() < 100)  
  60.         {  
  61.             //把轮廓面积不足100的区域,放到容器contours2中,  
  62.             tempV.push_back(Point(x, y));  
  63.             tempV.push_back(Point(x, y+h));  
  64.             tempV.push_back(Point(x+w, y+h));  
  65.             tempV.push_back(Point(x+w, y));  
  66.             contours2.push_back(tempV);  
  67.             /*也可以直接用:contours2.push_back(*itc);代替上面的5条语句*/  
  68.             //contours2.push_back(*itc);  
  69.   
  70.             //删除轮廓面积不足100的区域,即用黑色填充轮廓面积不足100的区域:  
  71.             cv::drawContours(srcImage, contours2, -1, Scalar(0,0,0), CV_FILLED);  
  72.         }  
  73.         //保存图片  
  74.         sprintf(str, "%d.jpg", i++);  
  75.         cv::imshow("srcImage", srcImage);  
  76.         imwrite(str, srcImage);  
  77.         cv::waitKey(100);  
  78.         tempV.clear();  
  79.         ++itc;  
  80.     }  
  81.     return 0;  
  82. }  

【2】findContours的用法:

[cpp]  view plain  copy
  1. using namespace std;  
  2. using namespace cv;  
  3. using namespace cv::xphoto;  
  4. #include "stdafx.h"  
  5. #include <iostream>    
  6. #include<vector>  
  7. #include<algorithm>  
  8. #include <opencv2\opencv.hpp>    
  9. #include <opencv2\highgui\highgui.hpp>    
  10. using namespace std;  
  11. using namespace cv;  
  12.   
  13. //轮廓按照面积大小升序排序  
  14. bool ascendSort(vector<Point> a, vector<Point> b) {  
  15.     return a.size() < b.size();  
  16.   
  17. }  
  18.   
  19. //轮廓按照面积大小降序排序  
  20. bool descendSort(vector<Point> a, vector<Point> b) {  
  21.     return a.size() > b.size();  
  22. }  
  23.   
  24. //自己实现的将灰度图像转为三通道的BGR图像  
  25. cv::Mat gray2BGR(cv::Mat grayImg) {  
  26.     if (grayImg.channels() == 3)  
  27.         return grayImg;  
  28.     cv::Mat bgrImg = cv::Mat::zeros(grayImg.size(), CV_8UC3);  
  29.     std::vector<cv::Mat> bgr_channels;  
  30.     cv::split(bgrImg, bgr_channels);  
  31.     bgr_channels.at(0) = grayImg;  
  32.     bgr_channels.at(1) = grayImg;  
  33.     bgr_channels.at(2) = grayImg;  
  34.     cv::merge(bgr_channels, bgrImg);  
  35.     return bgrImg;  
  36. }  
  37.   
  38. //自定义的drawImage函数的功能类似于OpenCV的drawContours函数  
  39. cv::Mat drawImage(cv::Mat image, vector< vector< Point> > pointV) {  
  40.     cv::Mat destImage=image.clone();  
  41.     if (destImage.channels()==1)  
  42.     {  
  43.         destImage = gray2BGR(destImage);  
  44.     }  
  45.     for (size_t i=0;i<pointV.size();i++)  
  46.     {  
  47.         for (size_t j = 0; j<pointV.at(i).size(); j++)  
  48.         {  
  49.             cv::Point point = pointV.at(i).at(j);  
  50.             destImage.at<Vec3b>(point) = cv::Vec3b(0, 0, saturate_cast<uchar>(255-i*5));  
  51.         }  
  52.   
  53.     }  
  54.     return destImage;  
  55. }  
  56. int main() {  
  57.     Mat srcImage = imread("D:\\OpencvTest\\mask5.jpg");  
  58.     cv::imshow("srcImage", srcImage);  
  59.     Mat thresholdImage;  
  60.     Mat grayImage;  
  61.     cvtColor(srcImage, grayImage, CV_BGR2GRAY);  
  62.     threshold(grayImage, thresholdImage, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);  
  63.     cv::Mat mask = thresholdImage.clone();  
  64.     //(1)CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE  
  65.     vector< vector< Point> > contours1;  
  66.     findContours(mask, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);  
  67.     cv::Mat destImage = drawImage(mask, contours1);  
  68.     imshow("destImage", destImage);  
  69.   
  70.     //(2)CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE  
  71.     vector< vector< Point> > contours2;   
  72.     findContours(mask, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);  
  73.     cv::Mat destImage2 = drawImage(mask, contours2);  
  74.     imshow("destImage2", destImage2);  
  75.   
  76.     //(3)CV_RETR_LIST, CV_CHAIN_APPROX_NONE  
  77.     vector< vector< Point> > contours3;   
  78.     findContours(mask, contours3, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);  
  79.     cv::Mat destImage3 = drawImage(mask, contours3);  
  80.     imshow("destImage3", destImage3);  
  81.   
  82.   
  83.     //(4)CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE  
  84.     vector< vector< Point> > contours4;  
  85.     findContours(mask, contours4, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);  
  86.     cv::Mat destImage4 = drawImage(mask, contours4);  
  87.     imshow("destImage4", destImage4);  
  88.   
  89.   
  90.     //cv::Mat imge2 = gray2BGR(mask);  
  91.     //drawContours(imge2, contours4, -1, cv::Scalar(0, 0, 255), 1);  
  92.     //cv::fillConvexPoly(mask, contours1.at(0), cv::Scalar(255, 255, 255));  
  93.     cv::waitKey(0);  
  94.     return 0;  
  95. }  


如果你觉得该帖子帮到你,还望贵人多多支持,鄙人会再接再厉,继续努力的~

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值