In this chapter, we will cover:

  • Eroding and dilating images using morphological filters
  • Opening and closing images using morphological filters
  • Detecting edges and corners using morphological filters
  • Segmenting images using watersheds 分水岭算法
  • Extracting foreground objects with the GrabCut algorithm
Eroding、dilating、Opening、closing

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>int main()
{// Read input imagecv::Mat image= cv::imread("../binary.bmp" );if (!image.data)return 0;// Display the imagecv::namedWindow( "Image");cv::imshow( "Image",image);// Erode the imagecv::Mat eroded;cv::erode(image,eroded,cv::Mat());// Display the eroded imagecv::namedWindow( "Eroded Image");cv::imshow( "Eroded Image",eroded);// Dilate the imagecv::Mat dilated;cv::dilate(image,dilated,cv::Mat());// Display the dialted imagecv::namedWindow( "Dilated Image");cv::imshow( "Dilated Image",dilated);// Erode the image with a larger s.e.cv::Mat element(7,7,CV_8U,cv::Scalar(1));cv::erode(image,eroded,element);// Display the eroded imagecv::namedWindow( "Eroded Image (7x7)");cv::imshow( "Eroded Image (7x7)",eroded);// Erode the image 3 times.cv::erode(image,eroded,cv::Mat(),cv::Point(-1,-1),3);// Display the eroded imagecv::namedWindow( "Eroded Image (3 times)");cv::imshow( "Eroded Image (3 times)",eroded);// Close the imagecv::Mat element5(5,5,CV_8U,cv::Scalar(1));cv::Mat closed;cv::morphologyEx(image,closed,cv::MORPH_CLOSE,element5);// Display the opened imagecv::namedWindow( "Closed Image");cv::imshow( "Closed Image",closed);// Open the imagecv::Mat opened;cv::morphologyEx(image,opened,cv::MORPH_OPEN,element5);// Display the opened imagecv::namedWindow( "Opened Image");cv::imshow( "Opened Image",opened);// Close and Open the imagecv::morphologyEx(image,image,cv::MORPH_CLOSE,element5);cv::morphologyEx(image,image,cv::MORPH_OPEN,element5);// Display the close/opened imagecv::namedWindow( "Closed and Opened Image");cv::imshow( "Closed and Opened Image",image);cv::imwrite( "binaryGroup.bmp",image);// Read input imageimage= cv::imread("../binary.bmp");// Open and Close the imagecv::morphologyEx(image,image,cv::MORPH_OPEN,element5);cv::morphologyEx(image,image,cv::MORPH_CLOSE,element5);// Display the close/opened imagecv::namedWindow( "Opened and Closed Image");cv::imshow( "Opened and Closed Image",image);cv::waitKey();return 0;
}

  results:

Detecting edges and corners using morphological filters
morphoFeatures.h
#if !defined MORPHOF
#define MORPHOF#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>class MorphoFeatures {
private:// threshold to produce binary imageint threshold;// structuring elements used in corner detectioncv::Mat cross;cv::Mat diamond;cv::Mat square;cv::Mat x;public:MorphoFeatures() : threshold(-1),cross(5, 5, CV_8U, cv::Scalar(0)),diamond(5, 5, CV_8U, cv::Scalar(0)),square(5, 5, CV_8U, cv::Scalar(0)),x(5, 5, CV_8U, cv::Scalar(0)) {// Creating the cross-shaped structuring elementfor (int i = 0; i < 5; i++) {cross.at<uchar>(2, i) = 1;cross.at<uchar>(i, 2) = 1;}// Creating the diamond-shaped structuring elementdiamond.at<uchar>(0, 0) = 0;diamond.at<uchar>(0, 1) = 0;diamond.at<uchar>(1, 0) = 0;diamond.at<uchar>(4, 4) = 0;diamond.at<uchar>(3, 4) = 0;diamond.at<uchar>(4, 3) = 0;diamond.at<uchar>(4, 0) = 0;diamond.at<uchar>(4, 1) = 0;diamond.at<uchar>(3, 0) = 0;diamond.at<uchar>(0, 4) = 0;diamond.at<uchar>(0, 3) = 0;diamond.at<uchar>(1, 4) = 0;// Creating the x-shaped structuring elementfor (int i = 0; i < 5; i++) {x.at<uchar>(i, i) = 1;x.at<uchar>(4 - i, i) = 1;}}void setThreshold(int t) {if (t > 0)threshold = t;}int getThreshold() const {return threshold;}cv::Mat getEdges(const cv::Mat &image) {// Get the gradient imagecv::Mat result;cv::morphologyEx(image, result, cv::MORPH_GRADIENT, cv::Mat());// Apply threshold to obtain a binary imageapplyThreshold(result);return result;}void applyThreshold(cv::Mat &result) {// Apply threshold on resultif (threshold > 0) {cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV);}}cv::Mat getCorners(const cv::Mat &image) {cv::Mat result;// Dilate with a crosscv::dilate(image, result, cross);// Erode with a diamondcv::erode(result, result, diamond);cv::Mat result2;// Dilate with a xcv::dilate(image, result2, x);// Erode with a squarecv::erode(result2, result2, square);// Corners are obtained by differencing// the two closed imagescv::absdiff(result2, result, result);// Apply threshold to obtain a binary imageapplyThreshold(result);return result;}void drawOnImage(const cv::Mat &binary, cv::Mat &image) {cv::Mat_<uchar>::const_iterator it = binary.begin<uchar>();cv::Mat_<uchar>::const_iterator itend = binary.end<uchar>();// for each pixelfor (int i = 0; it != itend; ++it, ++i) {if (!*it) {cv::circle(image,cv::Point(i%image.step, i/image.step),5, cv::Scalar(255, 0, 0));}}}};#endif

  morph.cpp

#include <iostream>#include "morphoFeatures.h"int main() {cv::Mat image = cv::imread( "../building.jpg");cv::cvtColor(image, image, CV_BGR2GRAY);// Create the morphological features instanceMorphoFeatures morpho;morpho.setThreshold(40);// Get the edgescv::Mat edges;edges = morpho.getEdges(image);cv::namedWindow( "Edges Image", CV_WINDOW_AUTOSIZE);cv::imshow( "Edges Image", edges);// Get the cornerscv::Mat corners;corners = morpho.getCorners(image);// Display the corner on the imagemorpho.drawOnImage(corners, image);cv::namedWindow( "Corners on Image", CV_WINDOW_AUTOSIZE);cv::imshow( "Corners on Image", image);cv::waitKey(0);return 0;}

  results:

Segmenting images using watersheds
watershedSegment.h
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>class WatershedSegmenter {
private:cv::Mat markers;public:void setMarkers(const cv::Mat &markerImage) {// Convert to image of intsmarkerImage.convertTo(markers, CV_32S);}cv::Mat process(const cv::Mat &image) {// Apply watershedcv::watershed(image, markers);return markers;}// Return result in the form of an imagecv::Mat getSegmentation() {cv::Mat tmp;// all segment with label higher than 255// will be assigned value 255markers.convertTo(tmp, CV_8U);return tmp;}// Return watershed in the form of an imagecv::Mat getWatersheds() {cv::Mat tmp;// Each pixel p is transform into// 255p + 255 befor conversionmarkers.convertTo(tmp, CV_8U, 255, 255);return tmp;}
};

  

// Read input imagecv::Mat image = cv::imread( "../group.jpg");if (!image.data) {return 0;}// Display the imagecv::namedWindow( "Original Image");cv::imshow( "Original Image", image);// Get the binary imagecv::Mat binary;binary = cv::imread( "../binary.bmp", 0);// Display the binary imagecv::namedWindow( "Binary Image");cv::imshow( "Binary Image", binary);// Eliminate noise and smaller objectscv::Mat fg;cv::erode(binary, fg, cv::Mat(), cv::Point(-1, -1), 6);// Display the foreground imagecv::namedWindow( "Foreground Image");cv::imshow( "Foreground Image", fg);

  results:

// Identify image pixels without objectscv::Mat bg;cv::dilate(binary, bg, cv::Mat(), cv::Point(-1, -1), 6);cv::threshold(bg, bg, 1, 128, cv::THRESH_BINARY_INV);// Display the backgroud imagecv::namedWindow( "Background Image");cv::imshow( "Background Image", bg);

  results:

// Show markers imagecv::Mat markers(binary.size(), CV_8U, cv::Scalar(0));markers = fg + bg;cv::namedWindow( "Markers");cv::imshow( "Markers", markers);

  

// Create watershed segmentation objectWatershedSegmenter segmenter;// Set markers and processsegmenter.setMarkers(markers);segmenter.process(image);// Display segmentation resultcv::namedWindow( "Segmentation");cv::imshow( "Segmentation", segmenter.getSegmentation());// Display watershedscv::namedWindow( "Watershed");cv::imshow( "Watershed", segmenter.getWatersheds());

  

// Open another image------------------------------------image = cv::imread( "../tower.jpg");// Identify background pixelscv::Mat imageMask(image.size(), CV_8U, cv::Scalar(0));cv::rectangle(imageMask, cv::Point(5, 5), cv::Point(image.cols - 5, image.rows - 5), cv::Scalar(255), 3);// Identify forground pixels (in the middle of the image)cv::rectangle(imageMask, cv::Point(image.cols / 2 - 10, image.rows / 2 - 10),cv::Point(image.cols / 2 + 10, image.rows / 2 + 10), cv::Scalar(1), 10);// Set markers and processsegmenter.setMarkers(imageMask);segmenter.process(image);// Display the image with markerscv::rectangle(image, cv::Point(5, 5), cv::Point(image.cols - 5, image.rows - 5), cv::Scalar(255, 255, 255), 3);cv::rectangle(image, cv::Point(image.cols / 2 - 10, image.rows / 2 - 10),cv::Point(image.cols / 2 + 10, image.rows / 2 + 10), cv::Scalar(1, 1, 1), 10);cv::namedWindow( "Image with marker");cv::imshow( "Image with marker", image);// Display watershedscv::namedWindow( "Watersheds of foreground object");cv::imshow( "Watersheds of foreground object", segmenter.getWatersheds());

  results:

Extracting foreground objects with the GrabCut algorithm
// Open another imageimage = cv::imread( "../tower.jpg");// define bounding rectangecv::Rect rectangle(50, 70, image.cols - 150, image.rows - 180);cv::Mat result;  // segmentation result (4 possible values)cv::Mat bgModel, fgModel; // the models (internally used)// GrabCut segmentationcv::grabCut(image,          // input imageresult,                     // segmentation resultrectangle,            // rectangle containing foregroundbgModel, fgModel,     // models1,                          //number of iterationscv::GC_INIT_WITH_RECT// use rectangle);// Get the pixles marked as likely foregroundcv::compare(result, cv::GC_PR_FGD, result, cv::CMP_EQ);// Generate output imagecv::Mat foreground(image.size(), CV_8UC3, cv::Scalar(255, 255, 255));image.copyTo(foreground, result); // bg pixels not copied// draw rectangle on original imagecv::rectangle(image, rectangle, cv::Scalar(255,255,255),1);cv::namedWindow( "Image");cv::imshow( "Image",image);// display resultcv::namedWindow( "Segmented Image");cv::imshow( "Segmented Image",foreground);

  

// Open another imageimage= cv::imread("../group.jpg");// define bounding rectanglecv::Rect rectangle2(10,100,380,180);cv::Mat bkgModel,fgrModel; // the models (internally used)// GrabCut segmentationcv::grabCut(image,   // input imageresult, // segmentation resultrectangle2,bkgModel,fgrModel,5,cv::GC_INIT_WITH_RECT);// Get the pixels marked as likely foreground//   cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);result= result&1;foreground.create(image.size(),CV_8UC3);foreground.setTo(cv::Scalar(255,255,255));image.copyTo(foreground,result); // bg pixels not copied// draw rectangle on original imagecv::rectangle(image, rectangle2, cv::Scalar(255,255,255),1);cv::namedWindow( "Image 2");cv::imshow( "Image 2",image);// display resultcv::namedWindow( "Foreground objects");cv::imshow( "Foreground objects",foreground);

  

转载于:https://www.cnblogs.com/starlitnext/p/3861398.html

Learning OpenCV Lecture 4 (Transforming Images with Morphological Operations)相关推荐

  1. Learning OpenCV Lecture 5 (Filtering the Images)

    In this chapter, we will cover: Filtering images using low-pass filters Filtering images using a med ...

  2. 写在前面的一些话:《Learning OpenCV》中文版 .

    2009-09-17 15:51 7578人阅读 评论(4) 收藏 举报 <!-- /* Font Definitions */ @font-face {font-family:Helvetic ...

  3. Python-OpenCV 笔记4 -- 形态学操作(Morphological Operations)

    Python-OpenCV 笔记4 – 形态学操作(Morphological Operations) 1.腐蚀(Erosion) # 函数原型 erode(src, kernel[, dst[, a ...

  4. OpenCV使用inRange的阈值操作Thresholding Operations

    OpenCV使用inRange的阈值操作Thresholding Operations 使用inRange的阈值操作 目标 理论 HSV色彩空间 代码 解释 结果 使用inRange的阈值操作 目标 ...

  5. OpenCV在矩阵上进行Mask 运算operations

    OpenCV在矩阵上进行Mask 运算operations OpenCV在矩阵上进行Mask 运算operations 我们的测试用例 代码 基本方法 filter2D功能 OpenCV在矩阵上进行M ...

  6. Learning OpenCV的中文版

    O'REILLY最近刚刚出版了一本相当不错的OpenCV书籍,名字叫<Leaning OpenCV>,该书的作者是很出名的 Gary Bradski 和 Adrain Kaebler.Ga ...

  7. [阅读体会] 学习OpenCV 3 (Learning OpenCV 3)

    文章目录 书中实用的资料站点 第一章 书中实用的资料站点 示例代码:https://github.com/oreillymedia/Learning-OpenCV-3_examples 书籍官网:ht ...

  8. Learning Opencv 3 —— 七章 Opencv 中的函子

    Opencv 函数 Principal Component Analysis (cv::PCA) 主成分分析主要完成的功能是从高维空间中抽取其中的若干维,并使得保留的维度能够保留原始数据的绝大多数信息 ...

  9. Learning opencv续不足(七)线图像的设计D

    因为线图像startline有了起点和终点,我们就可以用DDA法求出线上所有点,任意斜率直线通过四象限八区域查表法界定.我们只示范一个区域:函数为: public PointF DdaFindPtIm ...

最新文章

  1. 多快好省的宏基因组研究技巧
  2. Java提高—对象克隆(复制)/对象属性拷贝
  3. 【Linux】Linux服务器(centos7)环境搭建java/python3/nginx
  4. aliyun gradle 代理_gradle|gradle 配置阿里云镜像和插件镜像
  5. 用matlab录制声音然后进行读取和播放
  6. redis logfile 只读_docker 配置redis主从,哨兵sentinel
  7. 《推荐系统笔记(十二)》聚类生成标签以及基于标签的TopN推荐
  8. wininet InternetOpen\InternetOpenUrl\InternetReadFile 等
  9. vue单向数据绑定和双向数据绑定
  10. js中动态获取页面的高度和宽度的方法总结
  11. (入门、全面、通用)树莓派Raspbian系统安装配置,篇一
  12. UpdateData函数的用法
  13. ArcGIS按像元栅格值提取栅格
  14. 画廊php网站,美术画室画廊艺术设计网站整站源码 v5.7sp1
  15. 64位系统究竟牛逼在哪里?
  16. python爬取旅游信息_用Python爬取分析全国旅游数据-Go语言中文社区
  17. 家用计算机的普及英语作文,优秀高二英语作文:计算机
  18. 北津独石[阳江民俗文化]
  19. Ansible的task执行方式控制:forks以及serial
  20. java.sql.SQLException: Access denied for user ''@'localhost' (using password: YES)

热门文章

  1. JSON.parse()和SON.stringify()
  2. 2019-06-03 Java学习日记 day24 多线程
  3. [转]为什么Java中的HashMap默认加载因子是0.75
  4. 斯坦福机器学习视频笔记 Week6 关于机器学习的建议 Advice for Applying Machine Learning...
  5. 【转】MySQL分库分表环境下全局ID生成方案
  6. 关于动态创建控件性能提高 以及 SuspendLayout ResumeLayout 的使用
  7. POJ 1364 King (差分约束系统)
  8. Cocos2dx-demo演示项目:Part1
  9. hdoj1087 (DP--LIS)
  10. 9号团队-团队任务4:每日立会(2018-11-26,2018-11-27)