使用vs2019创建MFC项目,利用OpenCv实现了9个图像处理功能。分别是模糊化,锐化,羽化,腐蚀,膨胀,边缘检测,灰度化,放大,缩小功能。利用MFC图形化界面,用户点击想要实现的功能按钮,即可实现对图片的处理。
1.模糊化:
平滑,也称为模糊,是一种简单且经常使用的图像处理操作。要执行平滑操作,我们将对图像应用滤镜。最常见的滤波器类型是线性的,其中输出像素的值(即G(i ,j )被确定为输入像素值的加权和(即F(i + k ,j + l )):
h (k ,l )被称为内核,它只不过是过滤器的系数。它有助于将滤波器可视化为在图像上滑动的系数窗口。
Mat imageSource = imread("timg.jpg");
Mat imageResult = imageSource.clone();
RNG rng;
int randomNum;
int Number = 5;
for (int i = 0; i < imageSource.rows - Number; i++)
for (int j = 0; j < imageSource.cols - Number; j++)
{
randomNum = rng.uniform(0, Number);
imageResult.at<Vec3b>(i, j)[0] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[0];
imageResult.at<Vec3b>(i, j)[1] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[1];
imageResult.at<Vec3b>(i, j)[2] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[2];
}
imshow("模糊化效果", imageResult);
运行截图:
2.锐化:
锐化滤波器则使用邻域的微分作为算子,增大邻域间像素的差值,使图像的突变部分变的更加明显。锐化的作用是加强图像的边沿和轮廓。
Mat Kernel = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(srcCopy, dst, srcCopy.depth(), Kernel);
运行截图:
3.羽化:
羽化值越大,朦胧范围越宽,羽化值越小,朦胧范围越窄。可根据你想留下图的大小来调节。
算法分析:
1、通过对rgb值增加额外的V值实现朦胧效果
2、通过控制V值的大小实现范围控制。
3、V = 255 * 当前点Point距中点距离的平方s1 / (顶点距中点的距离平方 *mSize)s2;
4、s1 有根据 ratio 修正 dx dy值。
for (int y = 0; y < heigh; y++)
{
uchar* imgP = img.ptr<uchar>(y);
uchar* dstP = dst.ptr<uchar>(y);
for (int x = 0; x < width; x++)
{
int b = imgP[3 * x];
int g = imgP[3 * x + 1];
int r = imgP[3 * x + 2];
float dx = centerX - x;
float dy = centerY - y;
if (width > heigh)
dx = (dx * ratio);
else
dy = (dy * ratio);
int dstSq = dx * dx + dy * dy;
float v = ((float)dstSq / diff) * 255;
r = (int)(r + v);
g = (int)(g + v);
b = (int)(b + v);
r = (r > 255 ? 255 : (r < 0 ? 0 : r));
g = (g > 255 ? 255 : (g < 0 ? 0 : g));
b = (b > 255 ? 255 : (b < 0 ? 0 : b));
dstP[3 * x] = (uchar)b;
dstP[3 * x + 1] = (uchar)g;
dstP[3 * x + 2] = (uchar)r;
}
}
运行截图:
4.腐蚀:
假设原图像中有一个前景物体,那么我们用一个结构元素去腐蚀原图的过程是这样的:遍历原图像的每一个像素,然后用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最小值,用这个最小值替换当前像素值。
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstimg;
erode(img, dstimg, element);
运行截图:
5.膨胀:
假设原图像中有一个前景物体,那么我们用一个结构元素去膨胀原图的过程是这样的:遍历原图像的每一个像素,然后用结构元素的中心点对准当前正在遍历的这个像素,然后取当前结构元素所覆盖下的原图对应区域内的所有像素的最大值,用这个最大值替换当前像素值。
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstimg;
dilate(img, dstimg, element);
运行截图:
6.边缘检测:
//载入原图
Mat srcImage = imread("timg.jpg");
Mat dstImage, edge, grayImage;
//【1】创建于src同类型和大小的矩阵dst
dstImage.create(srcImage.size(), srcImage.type());
//【2】将原图像转换成灰度图像
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
//【3】先使用3*3内核来降噪
blur(grayImage, edge, Size(3, 3));
//【4】运行Canny算子
Canny(edge, edge, 3, 9, 3);
//显示效果图
imshow("【效果图】Canny边缘检测", edge);
运行截图:
7.灰度化:
灰度化:加快处理速度 黑色到白色直接有不同的颜色深度(0,255),使用opencv 自带的灰度转换函数。
cvtColor(img, imgGray, CV_BGR2GRAY);
运行截图:
8.放大:
resize函数可以将源图像精确地转化为指定尺寸的目标图像。放大图像,使用CV_INTER_LINEAR。
resize(img, dst, Size(), 2, 2);//我长宽都变为原来的2倍
运行截图:
9.缩小:
resize函数可以将源图像精确地转化为指定尺寸的目标图像。
要缩小图像,使用CV_INETR_AREA来插值。
resize(img, dst, Size(), 0.5, 0.5);//我长宽都变为原来的0.5倍
运行截图:
void mohuhua(){
Mat imageSource = imread("timg.jpg");
Mat imageResult = imageSource.clone();
RNG rng;
int randomNum;
int Number = 5;
for (int i = 0; i < imageSource.rows - Number; i++)
for (int j = 0; j < imageSource.cols - Number; j++)
{
randomNum = rng.uniform(0, Number);
imageResult.at<Vec3b>(i, j)[0] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[0];
imageResult.at<Vec3b>(i, j)[1] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[1];
imageResult.at<Vec3b>(i, j)[2] = imageSource.at<Vec3b>(i + randomNum, j + randomNum)[2];
}
imshow("模糊化效果", imageResult);
waitKey();
}
void yuhua()
{
float mSize = 0.5;
Mat src = imread("timg.jpg", 1);
//imshow("src", src);
int width = src.cols;
int heigh = src.rows;
int centerX = width >> 1;
int centerY = heigh >> 1;
int maxV = centerX * centerX + centerY * centerY;
int minV = (int)(maxV * (1 - mSize));
int diff = maxV - minV;
float ratio = width > heigh ? (float)heigh / (float)width : (float)width / (float)heigh;
Mat img;
src.copyTo(img);
Scalar avg = mean(src);
Mat dst(img.size(), CV_8UC3);
Mat mask1u[3];
float tmp, r;
for (int y = 0; y < heigh; y++)
{
uchar* imgP = img.ptr<uchar>(y);
uchar* dstP = dst.ptr<uchar>(y);
for (int x = 0; x < width; x++)
{
int b = imgP[3 * x];
int g = imgP[3 * x + 1];
int r = imgP[3 * x + 2];
float dx = centerX - x;
float dy = centerY - y;
if (width > heigh)
dx = (dx * ratio);
else
dy = (dy * ratio);
int dstSq = dx * dx + dy * dy;
float v = ((float)dstSq / diff) * 255;
r = (int)(r + v);
g = (int)(g + v);
b = (int)(b + v);
r = (r > 255 ? 255 : (r < 0 ? 0 : r));
g = (g > 255 ? 255 : (g < 0 ? 0 : g));
b = (b > 255 ? 255 : (b < 0 ? 0 : b));
dstP[3 * x] = (uchar)b;
dstP[3 * x + 1] = (uchar)g;
dstP[3 * x + 2] = (uchar)r;
}
}
imshow("羽化", dst);
waitKey();
//imwrite("D:/img/羽化.jpg", dst);
}
void ruihua() {
//读入打开图像
Mat src, dst, srcCopy;
src = imread("timg.jpg");
srcCopy = src.clone();
if (srcCopy.empty()) {
cout << "加载图像失败" << endl;
}
//图像锐化
Mat Kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
filter2D(srcCopy, dst, srcCopy.depth(), Kernel);
namedWindow("锐化", WINDOW_AUTOSIZE);
imshow("锐化", dst);
waitKey();
}
void fushi() {
//载入图片
Mat img = imread("timg.jpg");
//进行腐蚀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstimg;
erode(img, dstimg, element);
//显示效果图
imshow("【效果图】腐蚀操作", dstimg);
waitKey();
}
void pengzhang() {
//载入图片
Mat img = imread("timg.jpg");
//进行膨胀操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstimg;
dilate(img, dstimg, element);
//显示效果图
imshow("【效果图】膨胀操作", dstimg);
waitKey();
}
void bianyuan() {
//载入原图
Mat srcImage = imread("timg.jpg");
Mat dstImage, edge, grayImage;
//【1】创建于src同类型和大小的矩阵dst
dstImage.create(srcImage.size(), srcImage.type());
//【2】将原图像转换成灰度图像
cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
//【3】先使用3*3内核来降噪
blur(grayImage, edge, Size(3, 3));
//【4】运行Canny算子
Canny(edge, edge, 3, 9, 3);
//显示效果图
imshow("【效果图】Canny边缘检测", edge);
waitKey();
}
void gray()
{
Mat img, imgGray, result;
img = imread("timg.jpg");
cvtColor(img, imgGray, CV_BGR2GRAY);
imshow("灰度图", imgGray);
waitKey();
}
void smaller()
{
Mat img = imread("timg.jpg");
Mat dst;
resize(img, dst, Size(), 0.5, 0.5);//我长宽都变为原来的0.5倍
imshow("缩小图", dst);
waitKey();
}
void bigger()
{
Mat img = imread("timg.jpg");
Mat dst;
resize(img, dst, Size(), 2, 2);//我长宽都变为原来的2倍
imshow("放大图", dst);
waitKey();}
还有一些可以提高的部分,比如图形化界面可以更美观,算法可以更有效率等。