Learning OpenCV Lecture 4 (Transforming Images with Morphological Operations)
- 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
#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:
#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:
#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:
// 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)相关推荐
- Learning OpenCV Lecture 5 (Filtering the Images)
In this chapter, we will cover: Filtering images using low-pass filters Filtering images using a med ...
- 写在前面的一些话:《Learning OpenCV》中文版 .
2009-09-17 15:51 7578人阅读 评论(4) 收藏 举报 <!-- /* Font Definitions */ @font-face {font-family:Helvetic ...
- Python-OpenCV 笔记4 -- 形态学操作(Morphological Operations)
Python-OpenCV 笔记4 – 形态学操作(Morphological Operations) 1.腐蚀(Erosion) # 函数原型 erode(src, kernel[, dst[, a ...
- OpenCV使用inRange的阈值操作Thresholding Operations
OpenCV使用inRange的阈值操作Thresholding Operations 使用inRange的阈值操作 目标 理论 HSV色彩空间 代码 解释 结果 使用inRange的阈值操作 目标 ...
- OpenCV在矩阵上进行Mask 运算operations
OpenCV在矩阵上进行Mask 运算operations OpenCV在矩阵上进行Mask 运算operations 我们的测试用例 代码 基本方法 filter2D功能 OpenCV在矩阵上进行M ...
- Learning OpenCV的中文版
O'REILLY最近刚刚出版了一本相当不错的OpenCV书籍,名字叫<Leaning OpenCV>,该书的作者是很出名的 Gary Bradski 和 Adrain Kaebler.Ga ...
- [阅读体会] 学习OpenCV 3 (Learning OpenCV 3)
文章目录 书中实用的资料站点 第一章 书中实用的资料站点 示例代码:https://github.com/oreillymedia/Learning-OpenCV-3_examples 书籍官网:ht ...
- Learning Opencv 3 —— 七章 Opencv 中的函子
Opencv 函数 Principal Component Analysis (cv::PCA) 主成分分析主要完成的功能是从高维空间中抽取其中的若干维,并使得保留的维度能够保留原始数据的绝大多数信息 ...
- Learning opencv续不足(七)线图像的设计D
因为线图像startline有了起点和终点,我们就可以用DDA法求出线上所有点,任意斜率直线通过四象限八区域查表法界定.我们只示范一个区域:函数为: public PointF DdaFindPtIm ...
最新文章
- 多快好省的宏基因组研究技巧
- Java提高—对象克隆(复制)/对象属性拷贝
- 【Linux】Linux服务器(centos7)环境搭建java/python3/nginx
- aliyun gradle 代理_gradle|gradle 配置阿里云镜像和插件镜像
- 用matlab录制声音然后进行读取和播放
- redis logfile 只读_docker 配置redis主从,哨兵sentinel
- 《推荐系统笔记(十二)》聚类生成标签以及基于标签的TopN推荐
- wininet InternetOpen\InternetOpenUrl\InternetReadFile 等
- vue单向数据绑定和双向数据绑定
- js中动态获取页面的高度和宽度的方法总结
- (入门、全面、通用)树莓派Raspbian系统安装配置,篇一
- UpdateData函数的用法
- ArcGIS按像元栅格值提取栅格
- 画廊php网站,美术画室画廊艺术设计网站整站源码 v5.7sp1
- 64位系统究竟牛逼在哪里?
- python爬取旅游信息_用Python爬取分析全国旅游数据-Go语言中文社区
- 家用计算机的普及英语作文,优秀高二英语作文:计算机
- 北津独石[阳江民俗文化]
- Ansible的task执行方式控制:forks以及serial
- java.sql.SQLException: Access denied for user ''@'localhost' (using password: YES)
热门文章
- JSON.parse()和SON.stringify()
- 2019-06-03 Java学习日记 day24 多线程
- [转]为什么Java中的HashMap默认加载因子是0.75
- 斯坦福机器学习视频笔记 Week6 关于机器学习的建议 Advice for Applying Machine Learning...
- 【转】MySQL分库分表环境下全局ID生成方案
- 关于动态创建控件性能提高 以及 SuspendLayout ResumeLayout 的使用
- POJ 1364 King (差分约束系统)
- Cocos2dx-demo演示项目:Part1
- hdoj1087 (DP--LIS)
- 9号团队-团队任务4:每日立会(2018-11-26,2018-11-27)