OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域
生活随笔
收集整理的這篇文章主要介紹了
OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
?OpenCV刪除面積小的區(qū)域 實(shí)現(xiàn)圖像二值化分割 標(biāo)記連通區(qū)域
? ?【尊重原創(chuàng),轉(zhuǎn)載請注明出處】http://blog.csdn.net/guyuealian/article/details/78142749
? ?之前本博客在Matlab實(shí)現(xiàn)了《Matlab形態(tài)學(xué)圖像處理:二值圖像分割 標(biāo)記連通區(qū)域和重心位置 刪除連通區(qū)域》http://blog.csdn.net/guyuealian/article/details/71440949,現(xiàn)在本人使用OpenCV實(shí)現(xiàn)這一功能:對圖像進(jìn)行二值化分割,并用“紅色矩形”標(biāo)記連通區(qū)域的面積,為了減少噪聲的干擾,刪除面積小的區(qū)域,代碼中將連通區(qū)域面積(像素個數(shù))不足100的區(qū)域認(rèn)為是噪聲點(diǎn),并將其刪除(即置為背景黑色)。本人制作了一個GIF動畫圖,以便大家觀看效果圖:
? ?之前本博客在Matlab實(shí)現(xiàn)了《Matlab形態(tài)學(xué)圖像處理:二值圖像分割 標(biāo)記連通區(qū)域和重心位置 刪除連通區(qū)域》http://blog.csdn.net/guyuealian/article/details/71440949,現(xiàn)在本人使用OpenCV實(shí)現(xiàn)這一功能:對圖像進(jìn)行二值化分割,并用“紅色矩形”標(biāo)記連通區(qū)域的面積,為了減少噪聲的干擾,刪除面積小的區(qū)域,代碼中將連通區(qū)域面積(像素個數(shù))不足100的區(qū)域認(rèn)為是噪聲點(diǎn),并將其刪除(即置為背景黑色)。本人制作了一個GIF動畫圖,以便大家觀看效果圖:
OpenCV參考代碼如下:
#include "stdafx.h" #include <iostream> #include<vector> #include<algorithm> #include <opencv2\opencv.hpp> #include <opencv2\highgui\highgui.hpp> using namespace std; using namespace cv;//輪廓按照面積大小升序排序 bool ascendSort(vector<Point> a, vector<Point> b) {return a.size() < b.size();}//輪廓按照面積大小降序排序 bool descendSort(vector<Point> a, vector<Point> b) {return a.size() > b.size(); } int main() {Mat srcImage = imread("D:\\OpencvTest\\123.jpg");Mat thresholdImage;Mat grayImage;cvtColor(srcImage, grayImage, CV_BGR2GRAY);threshold(grayImage, thresholdImage, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);//Mat resultImage;//thresholdImage.copyTo(resultImage);vector< vector< Point> > contours; //用于保存所有輪廓信息vector< vector< Point> > contours2; //用于保存面積不足100的輪廓vector<Point> tempV; //暫存的輪廓findContours(thresholdImage, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//cv::Mat labels;//int N = connectedComponents(resultImage, labels, 8, CV_16U);//findContours(labels, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//輪廓按照面積大小進(jìn)行升序排序sort(contours.begin(), contours.end(), ascendSort);//升序排序vector<vector<Point> >::iterator itc = contours.begin();int i = 0;while (itc != contours.end()){//獲得輪廓的矩形邊界Rect rect = boundingRect(*itc);int x = rect.x;int y = rect.y;int w = rect.width;int h = rect.height;//繪制輪廓的矩形邊界cv::rectangle(srcImage, rect, { 0, 0, 255 }, 1);//保存圖片char str[10];sprintf(str, "%d.jpg", i++);cv::imshow("srcImage", srcImage);imwrite(str, srcImage);waitKey(1000);if (itc->size() < 100){//把輪廓面積不足100的區(qū)域,放到容器contours2中,tempV.push_back(Point(x, y));tempV.push_back(Point(x, y+h));tempV.push_back(Point(x+w, y+h));tempV.push_back(Point(x+w, y));contours2.push_back(tempV);/*也可以直接用:contours2.push_back(*itc);代替上面的5條語句*///contours2.push_back(*itc);//刪除輪廓面積不足100的區(qū)域,即用黑色填充輪廓面積不足100的區(qū)域:cv::drawContours(srcImage, contours2, -1, Scalar(0,0,0), CV_FILLED);}//保存圖片sprintf(str, "%d.jpg", i++);cv::imshow("srcImage", srcImage);imwrite(str, srcImage);cv::waitKey(100);tempV.clear();++itc;}return 0; }【2】findContours的用法:
using namespace std; using namespace cv; using namespace cv::xphoto; #include "stdafx.h" #include <iostream> #include<vector> #include<algorithm> #include <opencv2\opencv.hpp> #include <opencv2\highgui\highgui.hpp> using namespace std; using namespace cv;//輪廓按照面積大小升序排序 bool ascendSort(vector<Point> a, vector<Point> b) {return a.size() < b.size();}//輪廓按照面積大小降序排序 bool descendSort(vector<Point> a, vector<Point> b) {return a.size() > b.size(); }//自己實(shí)現(xiàn)的將灰度圖像轉(zhuǎn)為三通道的BGR圖像 cv::Mat gray2BGR(cv::Mat grayImg) {if (grayImg.channels() == 3)return grayImg;cv::Mat bgrImg = cv::Mat::zeros(grayImg.size(), CV_8UC3);std::vector<cv::Mat> bgr_channels;cv::split(bgrImg, bgr_channels);bgr_channels.at(0) = grayImg;bgr_channels.at(1) = grayImg;bgr_channels.at(2) = grayImg;cv::merge(bgr_channels, bgrImg);return bgrImg; }//自定義的drawImage函數(shù)的功能類似于OpenCV的drawContours函數(shù) cv::Mat drawImage(cv::Mat image, vector< vector< Point> > pointV) {cv::Mat destImage=image.clone();if (destImage.channels()==1){destImage = gray2BGR(destImage);}for (size_t i=0;i<pointV.size();i++){for (size_t j = 0; j<pointV.at(i).size(); j++){cv::Point point = pointV.at(i).at(j);destImage.at<Vec3b>(point) = cv::Vec3b(0, 0, saturate_cast<uchar>(255-i*5));}}return destImage; } int main() {Mat srcImage = imread("D:\\OpencvTest\\mask5.jpg");cv::imshow("srcImage", srcImage);Mat thresholdImage;Mat grayImage;cvtColor(srcImage, grayImage, CV_BGR2GRAY);threshold(grayImage, thresholdImage, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);cv::Mat mask = thresholdImage.clone();//(1)CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLEvector< vector< Point> > contours1;findContours(mask, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);cv::Mat destImage = drawImage(mask, contours1);imshow("destImage", destImage);//(2)CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONEvector< vector< Point> > contours2; findContours(mask, contours2, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);cv::Mat destImage2 = drawImage(mask, contours2);imshow("destImage2", destImage2);//(3)CV_RETR_LIST, CV_CHAIN_APPROX_NONEvector< vector< Point> > contours3; findContours(mask, contours3, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);cv::Mat destImage3 = drawImage(mask, contours3);imshow("destImage3", destImage3);//(4)CV_RETR_CCOMP, CV_CHAIN_APPROX_NONEvector< vector< Point> > contours4;findContours(mask, contours4, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE);cv::Mat destImage4 = drawImage(mask, contours4);imshow("destImage4", destImage4);//cv::Mat imge2 = gray2BGR(mask);//drawContours(imge2, contours4, -1, cv::Scalar(0, 0, 255), 1);//cv::fillConvexPoly(mask, contours1.at(0), cv::Scalar(255, 255, 255));cv::waitKey(0);return 0; }如果你覺得該帖子幫到你,還望貴人多多支持,鄙人會再接再厲,繼續(xù)努力的~
總結(jié)
以上是生活随笔為你收集整理的OpenCV删除面积小的区域 实现图像二值化分割 标记连通区域的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCV图像剪切的扩展和高级用法:任
- 下一篇: 图像中某点绕点旋转后的坐标,图像旋转坐标