OpenCV c++ 图像腐蚀、膨胀

图像腐蚀

作用:将目标元素收缩。面积较小的连通域可以通过腐蚀操作消除,从而减少噪声导致的计数错误。

步骤:

  1. 构建结构元素
  2. 扫描原图,找到第一个像素为1的点(因为是二值图,非0即1)
  3. 将预先设定好的形状以及原点位置的结构元素的原点移动到该点
  4. 判断该结构元素覆盖范围内的图像的像素值是否全部为1,如果是,则腐蚀后图像相同位置上的像素值为1,如果至少有一个像素值为0,则腐蚀后图像的相同位置上的像素值为0
  5. 对原图中所有像素值为1的点重复进行步骤3和4

结构元素:矩形、十字、椭圆

在腐蚀多通道时,每个通道独立进行腐蚀运算

腐蚀过程只针对非零元素,所以零像素背景,腐蚀操作后图像内容变瘦小;255像素背景,腐蚀操作后图像内容变粗大

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;

//绘制包含区域函数
void drawState(Mat& img, int number, Mat centroid, Mat stats, String str) {
	//生成随机颜色,用于区分不同连通域
	RNG rng(10086);
	vector<Vec3b> colors;
	
	for (int i = 0; i < number; i++) {
		//使用均匀分布的随机数确定颜色
		Vec3b vec3 = Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256));
		colors.push_back(vec3);
	}


	for (int i = 1; i < number; i++) {
		//中心位置
		int center_x = centroid.at<double>(i, 0);
		int center_y = centroid.at<double>(i, 1);
		//矩形边框
		int x = stats.at<int>(i, CC_STAT_LEFT);
		int y = stats.at<int>(i, CC_STAT_TOP);
		int w = stats.at<int>(i, CC_STAT_WIDTH);
		int h = stats.at<int>(i, CC_STAT_HEIGHT);
		int area = stats.at<int>(i, CC_STAT_AREA);
		//中心位置绘制
		circle(img, Point(center_x, center_y), 2, Scalar(0, 255, 0), 2, 8, 0);
		//外接矩阵
		Rect rect(x, y, w, h);
		rectangle(img, rect, colors[i], 1, 8, 0);
		putText(img, format("%d", i), Point(center_x, center_y), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 255), 1);
		cout << "number" << i << ",area" << area << endl;
	}
	imshow("str", img);

}

int main(int argc, char** argv) {
	//QuickDemo qd;
	//qd.myFilter_demo(src);

	//生成用于腐蚀的原图
	Mat src = (Mat_<uchar>(6, 6) << 0, 0, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255,
		0, 255, 255, 255, 255, 0,
		0, 255, 255, 255, 255, 0,
		0, 255, 255, 255, 255, 0,
		0, 0, 0, 0, 0, 0);
	Mat struct1, struct2;
	struct1 = getStructuringElement(0, Size(3, 3));		//矩形结构元素
	struct2 = getStructuringElement(1, Size(3, 3));		//十字结构元素

	Mat erodeSrc;		//存放腐蚀后的图像
	erode(src, erodeSrc, struct2);
	namedWindow("src", WINDOW_GUI_NORMAL);
	namedWindow("erodeSrc", WINDOW_GUI_NORMAL);
	imshow("src", src);
	imshow("erodeSrc", erodeSrc);

	Mat LearnCV_black= imread("D:/images/ren.jpg",IMREAD_ANYCOLOR);
	Mat LearnCV_write = imread("D:/images/wu.jpeg", IMREAD_ANYCOLOR);
	Mat erode_black1, erode_write1, erode_black2, erode_write2;

	//黑色背景图像腐蚀
	erode(LearnCV_black, erode_black1,struct1);
	erode(LearnCV_black, erode_black2, struct2);
	imshow("LearnCV_black", LearnCV_black);
	imshow("erode_black1", erode_black1);
	imshow("erode_black2", erode_black2);

	//白色背景图像腐蚀
	erode(LearnCV_write, erode_write1, struct1);
	erode(LearnCV_write, erode_write2, struct2);
	imshow("LearnCV_write", LearnCV_write);
	imshow("erode_write1", erode_write1);
	imshow("erode_write2", erode_write2);

	//验证腐蚀对小连通的去除
	Mat img = imread("D:/images/hua.jpeg");
	Mat img2;
	copyTo(img, img2, img);
	Mat rice, riceBW;
	//把图像转成二值图像
	cvtColor(img, rice, COLOR_BGR2GRAY);		//彩色-->灰度
	threshold(rice, riceBW, 50, 255, THRESH_BINARY);		//二值化

	Mat out, stats, centroid;
	int number = connectedComponentsWithStats(riceBW, out, stats, centroid, 8, CV_16U);
	drawState(img, number, centroid, stats, "未腐蚀时统计连通域");

	erode(riceBW, riceBW, struct1);		//对图像进行腐蚀
	number = connectedComponentsWithStats(riceBW, out, stats, centroid, 8, CV_16U);
	drawState(img2, number, centroid, stats, "腐蚀后统计连通域");

	
	waitKey(0);//此时图片显示时间为一直停留。(x)为x毫秒
	//destroyAllWindows();
	return 0;
}




图像膨胀

图像膨胀是图像腐蚀的相反过程

作用:连接图像中间隔的物体;填充小孔;增加物体大小;去除小物体;去除噪声;提取信息

过程:

结构元素

   原图

把核中心放在第一个元素:

最终效果:

在膨胀多通道时,每个通道独立进行膨胀运算

膨胀过程只针对非零元素,所以零像素背景,膨胀操作后图像内容变粗大;255像素背景,膨胀操作后图像内容变瘦小

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream>
#include<math.h>
#include <opencv2/imgproc.hpp>
#include<vector>
using namespace cv;
using namespace std;

Mat pixel_visit_demo(Mat& src) {
	Mat image ;
	image = src.clone();  //克隆
	int w = image.cols;
	int h = image.rows;
	int dims = image.channels();
	/*
	//数组
	for (int row = 0; row < h; row++) {
		for (int col = 0; col < w; col++) {
			if (dims == 1) {		//单通道灰度图
				int pv = image.at<uchar>(row, col);		//得到像素值(行,列)
				image.at<uchar>(row, col) = 255 - pv;	//给像素值重新赋值(取反)
			}
			if (dims == 3) {		//三通道彩色图
				Vec3b bgr = image.at<Vec3b>(row, col);	//opencv特定类型,获取三维颜色,3个值
				image.at<Vec3b>(row, col)[0] = 255 - bgr[0];	//对彩色图像读取像素值,并改写
				image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
				image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
			}
		}
	}*/
	//指针
	for (int row = 0; row < h; row++) {
		uchar* current_row = image.ptr<uchar>(row);
		for (int col = 0; col < w; col++) {
			if (dims == 1) {//灰度图
				int pv = *current_row;
				*current_row++ = 255 - pv;
			}
			if (dims == 3) {//彩色图
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
				*current_row++ = 255 - *current_row;
			}
		}
	}
	return( image);
};

int main(int argc, char** argv) {
	//QuickDemo qd;
	//qd.myFilter_demo(src);

	//生成用于腐蚀的原图
	Mat src = (Mat_<uchar>(6, 6) << 0, 0, 0, 0, 255, 0,
		0, 255, 255, 255, 255, 255,
		0, 255, 255, 255, 255, 0,
		0, 255, 255, 255, 255, 0,
		0, 255, 255, 255, 255, 0,
		0, 0, 0, 0, 0, 0);
	Mat struct1, struct2;
	struct1 = getStructuringElement(0, Size(3, 3));		//矩形结构元素
	struct2 = getStructuringElement(1, Size(3, 3));		//十字结构元素

	Mat dilateSrc;		//存放膨胀后的图像
	dilate(src, dilateSrc, struct2);
	namedWindow("src", WINDOW_GUI_NORMAL);
	namedWindow("dilateSrc", WINDOW_GUI_NORMAL);
	imshow("src", src);
	imshow("dilateSrc", dilateSrc);

	Mat LearnCV_black= imread("D:/images/black.png",IMREAD_ANYCOLOR);
	Mat LearnCV_write = pixel_visit_demo(LearnCV_black);
		
		
	Mat dilate_black1, dilate_write1, dilate_black2, dilate_write2;

	//黑色背景图像膨胀
	dilate(LearnCV_black, dilate_black1,struct1);
	dilate(LearnCV_black, dilate_black2, struct2);
	imshow("LearnCV_black", LearnCV_black);
	imshow("dilate_black1", dilate_black1);
	imshow("dilate_black2", dilate_black2);

	//白色背景图像腐蚀
	dilate(LearnCV_write, dilate_write1, struct1);
	dilate(LearnCV_write, dilate_write2, struct2);
	imshow("LearnCV_write", LearnCV_write);
	imshow("dilate_write1", dilate_write1);
	imshow("dilate_write2", dilate_write2);

	//比较腐蚀和膨胀的结果
	Mat erode_black1, resultXor, resultAnd;
	erode(LearnCV_black, erode_black1, struct1);
	bitwise_xor(erode_black1, dilate_write1, resultXor);
	bitwise_and(erode_black1, dilate_write1, resultAnd);
	imshow("resultXor", resultXor);
	imshow("resultAnd", resultAnd);


	
	waitKey(0);//此时图片显示时间为一直停留。(x)为x毫秒
	//destroyAllWindows();
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值