C++ Opencv 自写函数实现膨胀腐蚀处理
一、膨胀腐蚀学习笔记

二、代码及结果分享
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//定义腐蚀函数
void myErode(Mat Src, Mat Tem, Mat Dst)
{
int m = (Tem.rows - 1) / 2;
int n = (Tem.cols - 1) / 2;
for (int i = m; i < Src.rows - m; i++)//i、j的范围保证结构元始终在扩展后的图像内部
{
for (int j = n; j < Src.cols - n; j++)
{
Mat SrcROI = Src(Rect(j - m, i - n, Tem.cols, Tem.rows));
double sum = 0;
sum = SrcROI.dot(Tem);//矩阵对应位置相乘后求和
if (sum == 9)//结构元的9个元素均为1,和为9才能保证结构元完全包含于相应集合
Dst.at<uchar>(i, j) = 255;
else
Dst.at<uchar>(i, j) = 0;
}
}
}
//定义膨胀函数
void myDilate(Mat Src, Mat Tem, Mat Dst)
{
int m = (Tem.rows - 1) / 2;
int n = (Tem.cols - 1) / 2;
for (int i = m; i < Src.rows - m; i++)//i、j的范围保证结构元始终在扩展后的图像内部
{
for (int j = n; j < Src.cols - n; j++)
{
Mat SrcROI = Src(Rect(j - m, i - n, Tem.cols, Tem.rows));
double sum = 0;
sum = SrcROI.dot(Tem);//矩阵对应位置相乘后求和
if (sum != 0)//结构元的9个元素均为1,只要和不为0,就能说明结构元与相应集合有交集
Dst.at<uchar>(i, j) = 255;
else
Dst.at<uchar>(i, j) = 0;
}
}
}
int main()
{
Mat mImage = imread("dada.jpg", 0);
if (mImage.data == 0)
{
cerr << "Image reading error !" << endl;
system("pause");
return -1;
}
namedWindow("The original image", WINDOW_NORMAL);
imshow("The original image", mImage);
//设置阈值将图像二值化
const int binThreshold = 80;
for (int i = 0; i < mImage.rows; i++)
{
uchar* pImage = mImage.ptr<uchar>(i);
for (int j = 0; j < mImage.cols; j++)
{
if (pImage[j] > binThreshold)//事实上应将灰度值大于阈值的赋值为255,但为了方便后续膨胀腐蚀的计算,在这里将其赋值为1
pImage[j]= 1;
else
pImage[j] = 0;
}
}
//定义并初始化结构元
Mat mTemplate(3, 3, CV_8UC1, Scalar(1));
if (mTemplate.rows * mTemplate.cols % 2 == 0)
{
cerr << "The size doesn't meet the requirement !" << endl;
system("pause");
return -1;
}
//扩展图像边界
copyMakeBorder(mImage, mImage, mTemplate.rows, mTemplate.rows, mTemplate.cols, mTemplate.cols, BORDER_CONSTANT, Scalar(0));
//进行图像腐蚀
Mat mEResult = mImage.clone();
myErode(mImage, mTemplate, mEResult);
//进行图像膨胀
Mat mDResult = mImage.clone();
myDilate(mImage, mTemplate, mDResult);
//进行显示
namedWindow("The eroding image", WINDOW_NORMAL);
imshow("The eroding image", mEResult);
namedWindow("The dilating image", WINDOW_NORMAL);
imshow("The dilating image", mDResult);
waitKey();
destroyAllWindows();
return 0;
}

膨胀(dilate)和腐蚀(erode)均是对白色区域而言。由结果可明显看出,膨胀后的白色面积要比腐蚀后的大。由图像左下角的水印变化也可直观看出两种操作对图像的不同影响。
三、注意事项
在本次编程实现过程中,为了确定结构元是否包含于集合(或与集合是否有交集),需要让结构元中各元素与图像中对应位置像素值相乘后求和。Mat类型中有几种不同类型的乘法,在这里加以总结。
Mat A, B ;
3.1A.dot(B)
A、B对应位置元素相乘,之后将所有乘积相加求和,返回值是double型数字。要求A、B size必须相同。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
uchar A[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
uchar B[3][3] = { { 1,1,1 },{ 1,1,1 },{ 1,1,1 } };
Mat Src(3, 3, CV_8UC1, A);
Mat Dst(3, 3, CV_8UC1, B);
double Result = Src.dot(Dst);
cout << "Src:" << Src << endl;
cout << "Dst:" << Dst << endl;
cout << "Result:" << Result << endl;
system("pause");
return 0;
}

3.2A.mul(B)
A、B对应位置元素相乘,返回值是和A、B等大小,同类型的Mat型矩阵。要求A、B size必须相同。若计算结果溢出,则溢出值自动变为当前数据类型下允许的的最大值。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
uchar A[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
uchar B[3][3] = { { 1,1,1 },{ 1,1,1 },{ 1,1,1 } };
Mat Src(3, 3, CV_8UC1, A);
Mat Dst(3, 3, CV_8UC1, B);
Mat Result = Src.mul(Dst);
cout << "Src:" << Src << endl;
cout << "Dst:" << Dst << endl;
cout << "Result:" << Result << endl;
system("pause");
return 0;
}

注:错误之处,敬请雅正!
C++ Opencv 自写函数实现膨胀腐蚀处理的更多相关文章
- opencv学习之路(16)、膨胀腐蚀应用之走迷宫
一.分析 贴出应用图片以供直观了解 红色部分,因图而异(某些参数,根据图片的不同需要进行相应的修改) 二.代码 #include "opencv2/opencv.hpp" #inc ...
- opencv学习之路(14)、形态学之膨胀腐蚀
一.膨胀腐蚀概述(对高亮部分进行操作) 二.膨胀 三.腐蚀 四.代码 1.查看结构元素 #include<opencv2/opencv.hpp> #include<iostream& ...
- 常用的OpenCV 2.0函数速查
OpenCV 2.0函数释义列表 1.cvLoadImage:将图像文件加载至内存: 2.cvNamedWindow:在屏幕上创建一个窗口: 3.cvShowImage:在一个已创建好的窗口中显示图像 ...
- opencv 手写选择题阅卷 (二)字符识别
opencv 手写选择题阅卷 (二)字符识别 选择题基本上只需要识别ABCD和空五个内容,理论上应该识别率比较高的,识别代码参考了网上搜索的代码,因为参考的网址比较多,现在也弄不清是参考何处的代码了, ...
- 自写函数VB6 STUFF函数 和 VB.net 2010 STUFF函数 详解
'*************************************************************************'**模 块 名:自写函数VB6 STUFF函数 和 ...
- opencv 手写选择题阅卷 (四)Android端 手机应用开发
opencv 手写选择题阅卷 (四)Android 手机应用开发 在PC端把代码调通以后开始开发Android 手机应用,因为主要功能代码为C++代码,所以需要通过NDK编译,JAVA通过JNI方式调 ...
- opencv 手写选择题阅卷 (三)训练分类器
opencv 手写选择题阅卷 (三)训练分类器 1,分类器选择:SVM 本来一开始用的KNN分类器,但这个分类器目前没有实现保存训练数据的功能,所以选择了SVN分类器; 2,样本图像的预处理和特征提取 ...
- 由lib引发的血案(opencv找不函数问题)
在使用opencv中的函数时,连续两次遇到函数找不到的问题,第一次查时按照他人说的包含进一个头文件后,果真还真解决了:然而第二次在调用cvInpaint函数时包含进对应头文件,编译通过但运行不成功还是 ...
- (原)使用opencv的warpAffine函数对图像进行旋转
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/5070576.html 参考网址: http://stackoverflow.com/questions ...
随机推荐
- 浏览器标签栏logo添加
在<head > 中引入link,如下: <head> <link rel="icon" type="image/icon" hr ...
- 进军的socket
在学socket有时候我们会遇到这种问题: 解决方法一: 在服务端中加入:severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ...
- KNN Python实现
KNN Python实现 ''' k近邻(kNN)算法的工作机制比较简单,根据某种距离测度找出距离给定待测样本距离最小的k个训练样本,根据k个训练样本进行预测. 分类问题:k个点中出现频率最高的类别作 ...
- 一张图说明TCP和UCP协议
图片来自网络. 本来不想打字了,但是博客园有字数限制... 第一次 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认:SYN:同步序列编号( ...
- Python:每日一题008
题目: 判断101-200之间有多少个素数,并输出所有素数. 程序分析: 判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数. 个人思路及代码: li ...
- identityserver4 代码系列
链接:https://pan.baidu.com/s/1ePLwUxGpIPObwA8nnfDT9w 提取码:gr0x
- 获取ADO连接字符串
自己如何获取ADO连接字符串 有时候我们参考网上的ADO连接字符串写未必就能连接上数据库.今天详细介绍下这个很流行的如何获取ADO字符串的方法,就能很容易直观看到这个连接字符串是否真能连接上数据库.编 ...
- 89、instancetype和id的区别
1>instancetype在类型表示上,跟id一样,可以表示任何对象类型 2>instancetype只能用在返回值类型上,不能像id一样用在参数类型上 3>instancetyp ...
- 01 C语言程序设计--01 C语言基础--第3章 基本数据类型01
01.1.3.1序言 00:02:17 01.1.3.2 C语言中的基本元素和常量的概念 00:08:54 01.1.3.3示例--常量 00:12:08 01.1.3.4变量的概念和命名规则 00: ...
- Dom事件流、冒泡、捕获
Dom事件流 dom的结构是一个倒立的树状结构.当一个html元素触发事件时,事件会在dom的根节点和触发事件的元素节点之间传播,中间的节点都会收到该事件. 捕获:div元素触发事件时,事件先从根节点 ...