OPENCV4学习(28-39) 目录28.图像卷积filter2D()29.图像噪声的产生rand_double()rand_int()30.线性滤波blur()boxFilter()GaussianBlur()31.非线性滤波——中值滤波medianBlur()32.可分离滤波sepFilter2D()33.边缘检测一)Sobel()Scharr()getDerivKernels()34.边缘检测二Laplacian()Canny()35.连通域分析connectedComponents()connectedComponentsWithStats()36.图像距离变换distanceTransform()37.形态学操作——腐蚀getStructuringElement()erode()38.形态学操作——膨胀getStructuringElement()dilate()39.形态学应用morphologyEx()28.图像卷积filter2D()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //待卷积矩阵 uchar points[25] { 1,2,3,4,5, 6,7,8,9,10, 11,12,13,14,15, 16,17,18,19,20, 21,22,23,24,25 }; Mat img(5, 5, CV_8UC1, points); //卷积模板 Mat kernel (Mat_float(3, 3) 1, 2, 1, 2, 0, 2, 1, 2, 1); Mat kernel_norm kernel / 12; //卷积模板归一化 //未归一化卷积结果和归一化卷积结果 Mat result, result_norm; filter2D(img, result, CV_32F, kernel, Point(-1, -1), 2, BORDER_CONSTANT); filter2D(img, result_norm, CV_32F, kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT); cout result: endl result endl; cout result_norm: endl result_norm endl; //图像卷积 Mat lena imread(C:/opencv/learnOpenCV/lena.png); if (lena.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat lena_fillter; filter2D(lena, lena_fillter, -1, kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT); imshow(lena_fillter, lena_fillter); imshow(lena, lena); waitKey(0); return 0; }29.图像噪声的产生rand_double()rand_int()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; //盐噪声函数 void saltAndPepper(cv::Mat image, int n) { for (int k 0; kn / 2; k) { //随机确定图像中位置 int i, j; i cvflann::rand_int() % image.cols; //取余数运算保证在图像的列数内 j cvflann::rand_int() % image.rows; //取余数运算保证在图像的行数内 int write_black std::rand() % 2; //判定为白色噪声还是黑色噪声的变量 if (write_black 0) //添加白色噪声 { if (image.type() CV_8UC1) //处理灰度图像 { image.atuchar(j, i) 255; //白色噪声 } else if (image.type() CV_8UC3) //处理彩色图像 { image.atcv::Vec3b(j, i)[0] 255; //cv::Vec3b为opencv定义的一个3个值的向量类型 image.atcv::Vec3b(j, i)[1] 255; //[]指定通道B:0G:1R:2 image.atcv::Vec3b(j, i)[2] 255; } } else //添加黑色噪声 { if (image.type() CV_8UC1) { image.atuchar(j, i) 0; } else if (image.type() CV_8UC3) { image.atcv::Vec3b(j, i)[0] 0; //cv::Vec3b为opencv定义的一个3个值的向量类型 image.atcv::Vec3b(j, i)[1] 0; //[]指定通道B:0G:1R:2 image.atcv::Vec3b(j, i)[2] 0; } } } } int main() { Mat lena imread(C:/opencv/learnOpenCV/lena.png); Mat equalLena imread(C:/opencv/learnOpenCV/equalLena.png, IMREAD_ANYDEPTH); if (lena.empty() || equalLena.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat lena_G, equalLena_G; lena.copyTo(lena_G); equalLena.copyTo(equalLena_G); imshow(lena原图, lena); imshow(equalLena原图, equalLena); saltAndPepper(lena, 10000); //彩色图像添加椒盐噪声 saltAndPepper(equalLena, 10000); //灰度图像添加椒盐噪声 imshow(lena添加噪声, lena); imshow(equalLena添加噪声, equalLena); cout 下面是高斯噪声 endl; waitKey(0); Mat lena_noise Mat::zeros(lena.rows, lena.cols, lena.type()); Mat equalLena_noise Mat::zeros(equalLena.rows, equalLena.cols, equalLena.type()); imshow(lena原图, lena_G); imshow(equalLena原图, equalLena_G); RNG rng; //创建一个RNG类 rng.fill(lena_noise, RNG::NORMAL, 10, 20); //生成三通道的高斯分布随机数 rng.fill(equalLena_noise, RNG::NORMAL, 15, 30); //生成三通道的高斯分布随机数 imshow(三通道高斯噪声, lena_noise); imshow(单通道高斯噪声, equalLena_noise); lena_G lena_G lena_noise; //在彩色图像中添加高斯噪声 equalLena_G equalLena_G equalLena_noise; //在灰度图像中添加高斯噪声 //显示添加高斯噪声后的图像 imshow(lena添加噪声, lena_G); imshow(equalLena添加噪声, equalLena_G); waitKey(0); return 0; }30.线性滤波blur()boxFilter()GaussianBlur()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { Mat equalLena imread(C:/opencv/learnOpenCV/equalLena.png, IMREAD_ANYDEPTH); Mat equalLena_gauss imread(C:/opencv/learnOpenCV/equalLena_gauss.png, IMREAD_ANYDEPTH); Mat equalLena_salt imread(C:/opencv/learnOpenCV/equalLena_salt.png, IMREAD_ANYDEPTH); if (equalLena.empty() || equalLena_gauss.empty() || equalLena_salt.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat result_3, result_9; //存放不含噪声滤波结果后面数字代表滤波器尺寸 Mat result_3gauss, result_9gauss; //存放含有高斯噪声滤波结果后面数字代表滤波器尺寸 Mat result_3salt, result_9salt; //存放含有椒盐噪声滤波结果后面数字代表滤波器尺寸 //调用均值滤波函数blur()进行滤波 blur(equalLena, result_3, Size(3, 3)); blur(equalLena, result_9, Size(9, 9)); blur(equalLena_gauss, result_3gauss, Size(3, 3)); blur(equalLena_gauss, result_9gauss, Size(9, 9)); blur(equalLena_salt, result_3salt, Size(3, 3)); blur(equalLena_salt, result_9salt, Size(9, 9)); //显示不含噪声图像 imshow(equalLena , equalLena); imshow(result_3, result_3); imshow(result_9, result_9); //显示含有高斯噪声图像 imshow(equalLena_gauss, equalLena_gauss); imshow(result_3gauss, result_3gauss); imshow(result_9gauss, result_9gauss); //显示含有椒盐噪声图像 imshow(equalLena_salt, equalLena_salt); imshow(result_3salt, result_3salt); imshow(result_9salt, result_9salt); cout 接下来是方框滤波 endl; waitKey(0); Mat resultNorm, result; //方框滤波boxFilter()和sqrBoxFilter() boxFilter(equalLena, resultNorm, -1, Size(3, 3), Point(-1, -1), true); //进行归一化 boxFilter(equalLena, result, -1, Size(3, 3), Point(-1, -1), false); //不进行归一化 //显示处理结果 imshow(resultNorm, resultNorm); imshow(result, result); cout 接下来是高斯滤波 endl; waitKey(0); Mat result_5_G, result_9_G; //存放不含噪声滤波结果后面数字代表滤波器尺寸 Mat result_5gauss_G, result_9gauss_G; //存放含有高斯噪声滤波结果后面数字代表滤波器尺寸 Mat result_5salt_G, result_9salt_G; ////存放含有椒盐噪声滤波结果后面数字代表滤波器尺寸 //调用高斯滤波函数GaussianBlur()进行滤波 GaussianBlur(equalLena, result_5_G, Size(5, 5), 10, 20); GaussianBlur(equalLena, result_9_G, Size(9, 9), 10, 20); GaussianBlur(equalLena_gauss, result_5gauss_G, Size(5, 5), 10, 20); GaussianBlur(equalLena_gauss, result_9gauss_G, Size(9, 9), 10, 20); GaussianBlur(equalLena_salt, result_5salt_G, Size(5, 5), 10, 20); GaussianBlur(equalLena_salt, result_9salt_G, Size(9, 9), 10, 20); //显示不含噪声图像 imshow(equalLena , equalLena); imshow(result_5, result_5_G); imshow(result_9, result_9_G); //显示含有高斯噪声图像 imshow(equalLena_gauss, equalLena_gauss); imshow(result_5gauss, result_5gauss_G); imshow(result_9gauss, result_9gauss_G); //显示含有椒盐噪声图像 imshow(equalLena_salt, equalLena_salt); imshow(result_5salt, result_5salt_G); imshow(result_9salt, result_9salt_G); waitKey(0); return 0; }31.非线性滤波——中值滤波medianBlur()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { Mat img imread(C:/opencv/learnOpenCV/lena_salt.png, IMREAD_ANYCOLOR); Mat gray imread(C:/opencv/learnOpenCV/equalLena_salt.png, IMREAD_ANYCOLOR); Mat gray_g imread(C:/opencv/learnOpenCV/equalLena_gauss.png, IMREAD_ANYCOLOR); Mat imgResult3, imgResult9, grayResult3, grayResult9, gray_gResult3, gray_gResult9; medianBlur(img, imgResult3, 3); medianBlur(gray, grayResult3, 3); medianBlur(gray_g, gray_gResult3, 3); medianBlur(img, imgResult9, 9); medianBlur(gray, grayResult9, 9); medianBlur(gray_g, gray_gResult9, 9); imshow(imgResult3, imgResult3); imshow(grayResult3, grayResult3); imshow(gray_gResult3, gray_gResult3); imshow(imgResult9, imgResult9); imshow(grayResult9, grayResult9); imshow(gray_gResult9, gray_gResult9); waitKey(0); return 0; }32.可分离滤波sepFilter2D()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { float points[25] { 1,2,3,4,5, 6,7,8,9,10, 11,12,13,14,15, 16,17,18,19,20, 21,22,23,24,25 }; Mat data(5, 5, CV_32FC1, points); //X方向、Y方向和联合滤波器的构建 Mat a (Mat_float(3, 1) -1, 3, -1); Mat b a.reshape(1, 1); Mat ab a*b; //线性滤波的可分离性 Mat dataYX, dataY, dataXY, dataXY_sep; filter2D(data, dataY, -1, a, Point(-1, -1), 0, BORDER_CONSTANT); filter2D(dataY, dataYX, -1, b, Point(-1, -1), 0, BORDER_CONSTANT); filter2D(data, dataXY, -1, ab, Point(-1, -1), 0, BORDER_CONSTANT); sepFilter2D(data, dataXY_sep, -1, b, b, Point(-1, -1), 0, BORDER_CONSTANT); //验证高斯滤波的可分离性 Mat gaussX getGaussianKernel(3, 1); Mat gaussData, gaussDataXY; GaussianBlur(data, gaussData, Size(3, 3), 1, 1, BORDER_CONSTANT); sepFilter2D(data, gaussDataXY, -1, gaussX, gaussX, Point(-1, -1), 0, BORDER_CONSTANT); //输入两种高斯滤波的计算结果 cout gaussData endl gaussData endl; cout gaussDataXY endl gaussDataXY endl; //输出分离滤波和联合滤波的计算结果 cout dataY endl dataY endl; cout dataYX endl dataYX endl; cout dataXY endl dataXY endl; cout dataXY_sep endl dataXY_sep endl; //对图像的分离操作 Mat img imread(C:/opencv/lena.png); if (img.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat imgYX, imgY, imgXY; filter2D(img, imgY, -1, a, Point(-1, -1), 0, BORDER_CONSTANT); filter2D(imgY, imgYX, -1, b, Point(-1, -1), 0, BORDER_CONSTANT); filter2D(img, imgXY, -1, ab, Point(-1, -1), 0, BORDER_CONSTANT); imshow(img, img); imshow(imgY, imgY); imshow(imgYX, imgYX); imshow(imgXY, imgXY); waitKey(0); return 0; }33.边缘检测一)Sobel()Scharr()getDerivKernels()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //读取图像黑白图像边缘检测结果较为明显 Mat img imread(C:/opencv/equalLena.png, IMREAD_ANYCOLOR); if (img.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat resultX, resultY, resultXY; //X方向一阶边缘 Sobel(img, resultX, CV_16S, 1, 0, 1); convertScaleAbs(resultX, resultX); //Y方向一阶边缘 Sobel(img, resultY, CV_16S, 0, 1, 3); convertScaleAbs(resultY, resultY); //整幅图像的一阶边缘 resultXY resultX resultY; //显示图像 imshow(resultX, resultX); imshow(resultY, resultY); imshow(resultXY, resultXY); cout 接下来进行Scharr边缘的检测 endl; waitKey(0); //X方向一阶边缘 Scharr(img, resultX, CV_16S, 1, 0); convertScaleAbs(resultX, resultX); //Y方向一阶边缘 Scharr(img, resultY, CV_16S, 0, 1); convertScaleAbs(resultY, resultY); //整幅图像的一阶边缘 resultXY resultX resultY; //显示图像 imshow(resultX, resultX); imshow(resultY, resultY); imshow(resultXY, resultXY); cout 接下来生成边缘检测器 endl; waitKey(0); Mat sobel_x1, sobel_y1; //存放分离的Sobel算子 Mat scharr_x, scharr_y; //存放分离的Scharr算子 Mat sobelX1, scharrX; //存放最终算子 //一阶X方向Sobel算子 getDerivKernels(sobel_x1, sobel_y1, 1, 0, 3); sobel_x1 sobel_x1.reshape(CV_8U, 1); sobelX1 sobel_y1*sobel_x1; //计算滤波器 //X方向Scharr算子 getDerivKernels(scharr_x, scharr_y, 1, 0, FILTER_SCHARR); scharr_x scharr_x.reshape(CV_8U, 1); scharrX scharr_y*scharr_x; //计算滤波器 //输出结果 cout X方向一阶Sobel算子: endl sobelX1 endl; cout X方向Scharr算子: endl scharrX endl; waitKey(0); return 0; }34.边缘检测二Laplacian()Canny()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //读取图像黑白图像边缘检测结果较为明显 Mat img imread(C:/opencv/equalLena.png, IMREAD_ANYDEPTH); if (img.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat result, result_g, result_G; //未滤波提取边缘 Laplacian(img, result, CV_16S, 3, 1, 0); convertScaleAbs(result, result); //滤波后提取Laplacian边缘 GaussianBlur(img, result_g, Size(3, 3), 5, 0); //高斯滤波 Laplacian(result_g, result_G, CV_16S, 3, 1, 0); convertScaleAbs(result_G, result_G); //显示图像 imshow(result, result); imshow(result_G, result_G); cout 接下来进行Canny边缘检测 endl; waitKey(0); Mat resultHigh, resultLow, resultG; //大阈值检测图像边缘 Canny(img, resultHigh, 100, 200, 3); //小阈值检测图像边缘 Canny(img, resultLow, 20, 40, 3); //高斯模糊后检测图像边缘 GaussianBlur(img, resultG, Size(3, 3), 5); Canny(resultG, resultG, 100, 200, 3); //显示图像 imshow(resultHigh, resultHigh); imshow(resultLow, resultLow); imshow(resultG, resultG); waitKey(0); return 0; }35.连通域分析connectedComponents()connectedComponentsWithStats()#include opencv2\opencv.hpp #include iostream #include vector using namespace cv; using namespace std; int main() { //对图像进行距离变换 Mat img imread(C:/opencv/rice.png); if (img.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat rice, riceBW; //将图像转成二值图像用于统计连通域 cvtColor(img, rice, COLOR_BGR2GRAY); threshold(rice, riceBW, 50, 255, THRESH_BINARY); //生成随机颜色用于区分不同连通域 RNG rng(10086); Mat out; int number connectedComponents(riceBW, out, 8, CV_16U); //统计图像中连通域的个数 vectorVec3b 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); } //以不同颜色标记出不同的连通域 Mat result Mat::zeros(rice.size(), img.type()); int w result.cols; int h result.rows; for (int row 0; row h; row) { for (int col 0; col w; col) { int label out.atuint16_t(row, col); if (label 0) //背景的黑色不改变 { continue; } result.atVec3b(row, col) colors[label]; } } //显示结果 imshow(原图, img); imshow(标记后的图像, result); cout 接下来统计连通域信息 endl; waitKey(0); Mat stats, centroids; number connectedComponentsWithStats(riceBW, out, stats, centroids, 8, CV_16U); vectorVec3b colors_new; for (int i 0; i number; i) { //使用均匀分布的随机数确定颜色 Vec3b vec3 Vec3b(rng.uniform(0, 256), rng.uniform(0, 256), rng.uniform(0, 256)); colors_new.push_back(vec3); } //以不同颜色标记出不同的连通域 for (int i 1; i number; i) { // 中心位置 int center_x centroids.atdouble(i, 0); int center_y centroids.atdouble(i, 1); //矩形边框 int x stats.atint(i, CC_STAT_LEFT); int y stats.atint(i, CC_STAT_TOP); int w stats.atint(i, CC_STAT_WIDTH); int h stats.atint(i, CC_STAT_HEIGHT); int area stats.atint(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_new[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(标记后的图像, img); waitKey(0); return 0; }36.图像距离变换distanceTransform()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //构建建议矩阵用于求取像素之间的距离 Mat a (Mat_uchar(5, 5) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); Mat dist_L1, dist_L2, dist_C, dist_L12; //计算街区距离 distanceTransform(a, dist_L1, 1, 3, CV_8U); cout 街区距离 endl dist_L1 endl; //计算欧式距离 distanceTransform(a, dist_L2, 2, 5, CV_8U); cout 欧式距离 endl dist_L2 endl; //计算棋盘距离 distanceTransform(a, dist_C, 3, 5, CV_8U); cout 棋盘距离 endl dist_C endl; cout 对图像进行距离变换 endl; waitKey(0); Mat rice imread(C:/opencv/rice.png, IMREAD_GRAYSCALE); if (rice.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat riceBW, riceBW_INV; //将图像转成二值图像同时把黑白区域颜色互换 threshold(rice, riceBW, 50, 255, THRESH_BINARY); threshold(rice, riceBW_INV, 50, 255, THRESH_BINARY_INV); //距离变换 Mat dist, dist_INV; distanceTransform(riceBW, dist, 1, 3, CV_32F); //为了显示清晰将数据类型变成CV_32F distanceTransform(riceBW_INV, dist_INV, 1, 3, CV_8U); //显示变换结果 imshow(riceBW, riceBW); imshow(dist, dist); imshow(riceBW_INV, riceBW_INV); imshow(dist_INV, dist_INV); waitKey(0); return 0; }37.形态学操作——腐蚀getStructuringElement()erode()#include opencv2\opencv.hpp #include iostream #include vector using namespace cv; using namespace std; //绘制包含区域函数 void drawState(Mat img, int number, Mat centroids, Mat stats, String str) { RNG rng(10086); vectorVec3b 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 centroids.atdouble(i, 0); int center_y centroids.atdouble(i, 1); //矩形边框 int x stats.atint(i, CC_STAT_LEFT); int y stats.atint(i, CC_STAT_TOP); int w stats.atint(i, CC_STAT_WIDTH); int h stats.atint(i, CC_STAT_HEIGHT); // 中心位置绘制 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); } imshow(str, img); } int main() { //生成用于腐蚀的原图像 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); cout 文字腐蚀验证 endl; waitKey(0); Mat LearnCV_black imread(C:/opencv/LearnCV_black.png, IMREAD_ANYCOLOR); Mat erode_black1, erode_black2; //黑背景图像腐蚀 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); cout 验证腐蚀对小连通域的去除 endl; waitKey(0); Mat img imread(rice.png); if (img.empty()) { cout 请确认图像文件名称是否正确 endl; return -1; } Mat img2; copyTo(img, img2, img); //克隆一个单独的图像用于后期图像绘制 Mat rice, riceBW; //将图像转成二值图像用于统计连通域 cvtColor(img, rice, COLOR_BGR2GRAY); threshold(rice, riceBW, 50, 255, THRESH_BINARY); Mat out, stats, centroids; //统计图像中连通域的个数 int number connectedComponentsWithStats(riceBW, out, stats, centroids, 8, CV_16U); drawState(img, number, centroids, stats, 未腐蚀时统计连通域); //绘制图像 erode(riceBW, riceBW, struct1); //对图像进行腐蚀 number connectedComponentsWithStats(riceBW, out, stats, centroids, 8, CV_16U); drawState(img2, number, centroids, stats, 腐蚀后统计连通域); //绘制图像 waitKey(0); return 0; }38.形态学操作——膨胀getStructuringElement()dilate()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //生成用于膨胀的原图像 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; //存放膨胀后的图像 dilate(src, erodeSrc, struct2); namedWindow(src, WINDOW_GUI_NORMAL); namedWindow(dilateSrc, WINDOW_GUI_NORMAL); imshow(src, src); imshow(dilateSrc, erodeSrc); cout 文字膨胀 endl; waitKey(0); Mat LearnCV_black imread(C:/opencv/LearnCV_black.png, IMREAD_ANYCOLOR); Mat dilate_black1, dilate_black2; //黑背景图像膨胀 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); waitKey(0); return 0; }39.形态学应用morphologyEx()#include opencv2\opencv.hpp #include iostream using namespace cv; using namespace std; int main() { //用于验证形态学应用的二值化矩阵 Mat src (Mat_uchar(9, 12) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 0, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255, 0, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); namedWindow(src, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(src, src); //3×3矩形结构元素 Mat kernel getStructuringElement(0, Size(3, 3)); //对二值化矩阵进行形态学操作 Mat open, close, gradient, tophat, blackhat, hitmiss; //对二值化矩阵进行开运算 morphologyEx(src, open, MORPH_OPEN, kernel); namedWindow(open, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(open, open); //对二值化矩阵进行闭运算 morphologyEx(src, close, MORPH_CLOSE, kernel); namedWindow(close, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(close, close); //对二值化矩阵进行梯度运算 morphologyEx(src, gradient, MORPH_GRADIENT, kernel); namedWindow(gradient, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(gradient, gradient); //对二值化矩阵进行顶帽运算 morphologyEx(src, tophat, MORPH_TOPHAT, kernel); namedWindow(tophat, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(tophat, tophat); //对二值化矩阵进行黑帽运算 morphologyEx(src, blackhat, MORPH_BLACKHAT, kernel); namedWindow(blackhat, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(blackhat, blackhat); //对二值化矩阵进行击中击不中变换 morphologyEx(src, hitmiss, MORPH_HITMISS, kernel); namedWindow(hitmiss, WINDOW_NORMAL); //可以自由调节显示图像的尺寸 imshow(hitmiss, hitmiss); cout 用图像验证形态学操作效果 endl; waitKey(0); Mat keys imread(C:/opencv/keys.jpg, IMREAD_GRAYSCALE); imshow(原图像, keys); threshold(keys, keys, 80, 255, THRESH_BINARY); imshow(二值化后的keys, keys); //5×5矩形结构元素 Mat kernel_keys getStructuringElement(0, Size(5, 5)); Mat open_keys, close_keys, gradient_keys, tophat_keys, blackhat_keys, hitmiss_keys; //对图像进行开运算 morphologyEx(keys, open_keys, MORPH_OPEN, kernel_keys); imshow(open_keys, open_keys); //对图像进行闭运算 morphologyEx(keys, close_keys, MORPH_CLOSE, kernel_keys); imshow(close_keys, close_keys); //对图像进行梯度运算 morphologyEx(keys, gradient_keys, MORPH_GRADIENT, kernel_keys); imshow(gradient_keys, gradient_keys); //对图像进行顶帽运算 morphologyEx(keys, tophat_keys, MORPH_TOPHAT, kernel_keys); imshow(tophat_keys, tophat_keys); //对图像进行黑帽运算 morphologyEx(keys, blackhat_keys, MORPH_BLACKHAT, kernel_keys); imshow(blackhat_keys, blackhat_keys); //对图像进行击中击不中变换 morphologyEx(keys, hitmiss_keys, MORPH_HITMISS, kernel_keys); imshow(hitmiss_keys, hitmiss_keys); waitKey(0); return 0; }