简易图像滤镜
喜欢拍照的朋友肯定都接触过图像滤镜,一张图加了滤镜处理之后会有很意想不到的效果,今天说说图像滤镜的简易原理。
其实图像滤镜就是对图像的像素值有规律进行操作,下面介绍10种滤镜的原理,用于测试的原图如下图所示:
1、黑白滤镜
将彩色照片变成黑白照片,实质上是一个灰度化的过程。
彩色图像的像素值有3个通道,r, g, b。灰度化的过程就是使三通道的像素值相等,即:
b = b;
g = b;
r = b;
//灰度滤镜
void fun_gray(Mat &src, Mat &dst)
{
dst = src.clone();
for(int i=0;i<src.rows;i++)
for (int j = 0; j < src.cols; j++)
{
dst.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[0];
}
return;
}
结果图:
2、底片滤镜
将彩色照片变成底片效果,实质是对像素值取反,即:
b = 255 - b;
g = 255 - g;
r = 255 - r;
//底片滤镜
void fun_reverse(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
dst.at<Vec3b>(i, j)[0] = 255-src.at<Vec3b>(i, j)[0];
dst.at<Vec3b>(i, j)[1] = 255-src.at<Vec3b>(i, j)[1];
dst.at<Vec3b>(i, j)[2] = 255-src.at<Vec3b>(i, j)[2];
}
return;
}
效果图:
3、换色滤镜
将彩色照片换一种主色调,实质是取三通道r,g,b像素值的最大值和最小值的平均值,然后用该平均值代替某一通道的像素值,即:
value = max(r,g,b)+min(r,g,b)
b = value/2;
//换色滤镜
void fun_changeColor(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int max_value = src.at<Vec3b>(i, j)[0]>src.at<Vec3b>(i, j)[1]?src.at<Vec3b>(i, j)[0]:src.at<Vec3b>(i, j)[1];
max_value = max_value>src.at<Vec3b>(i, j)[2]? max_value:src.at<Vec3b>(i, j)[2];
int min_value = src.at<Vec3b>(i, j)[0]<src.at<Vec3b>(i, j)[1] ? src.at<Vec3b>(i, j)[0] : src.at<Vec3b>(i, j)[1];
min_value = min_value<src.at<Vec3b>(i, j)[2] ? min_value : src.at<Vec3b>(i, j)[2];
int value = (max_value + min_value) / 2;
dst.at<Vec3b>(i, j)[0] = value;
//dst.at<Vec3b>(i, j)[1] = value;
//dst.at<Vec3b>(i, j)[2] = value;
}
return;
}
效果图:
4、怀旧滤镜
将彩色照片的主色调换成一种怀旧的黄色,即:
b = (272 * r + 534 * g + 131 * b) / 1000;
g = (349 * r + 686 * g + 168 * b) / 1000;
r = (393 * r + 769 * g + 189 * b) / 1000;
//怀旧滤镜
void fun_old(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int b_new = (272 * r + 534 * g + 131 * b) / 1000;
int g_new = (349 * r + 686 * g + 168 * b) / 1000;
int r_new = (393 * r + 769 * g + 189 * b) / 1000;
if (b_new > 255) b_new = 255;
if (g_new > 255) g_new = 255;
if (r_new > 255) r_new = 255;
dst.at<Vec3b>(i, j)[0] = b_new;
dst.at<Vec3b>(i, j)[2] = g_new;
dst.at<Vec3b>(i, j)[1] = r_new;
}
return;
}
效果图:
5、火焰滤镜
将彩色照片增加一种燃烧的效果,即:
b =b*128/(g+r+1);
g = g*128/(r+b+1);
r = r*128/(g+b+1);
//熔岩滤镜
void fun_fire(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
dst.at<Vec3b>(i, j)[0] = min(b*128/(g+r+1),255);
dst.at<Vec3b>(i, j)[1] = min(g*128/(r+b+1),255);
dst.at<Vec3b>(i, j)[2] = min(r*128/(g+b+1),255);
}
return;
}
效果图:
6、冰封滤镜
将彩色照片增加一种冰冻的效果,即:
b = (b - g - r) * 1.2;
g = (g - r - b) * 1.2;
r = (r - g - b) * 1.2;
//冰雕滤镜
void fun_ice(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int b_new = (b - g - r) * 1.2;
int g_new = (g - r - b) * 1.2;
int r_new = (r - g - b) * 1.2;
dst.at<Vec3b>(i, j)[0] = b_new;
dst.at<Vec3b>(i, j)[1] = g_new;
dst.at<Vec3b>(i, j)[2] = r_new;
}
return;
}
效果可能不太好,如下图:
7、卡通滤镜
将彩色照片增加一种卡通的效果,即:
b = abs(b - g + b + r) * g / 256;
g = abs(b - g + b + r) * r / 256;
r = abs(g - b + g + r) * r / 256;
//卡通滤镜
void fun_cartoon(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int b_new = abs(b - g + b + r) * g / 256;
int g_new = abs(b - g + b + r) * r / 256;
int r_new = abs(g - b + g + r) * r / 256;
if (b_new > 255) b_new = 255;
if (g_new > 255) g_new = 255;
if (r_new > 255) r_new = 255;
dst.at<Vec3b>(i, j)[0] = b_new;
dst.at<Vec3b>(i, j)[1] = g_new;
dst.at<Vec3b>(i, j)[2] = r_new;
}
return;
}
效果图:
8、浮雕滤镜
将彩色照片增加一种浮雕的效果,即根据像素点灰度梯度值设置像素,即:
value = b1-b2; (b1和b2为相邻像素点的像素值)
b = value + 128;
g = value + 128;
r = value + 128; //128是为了将梯度增加,可以更改
//浮雕滤镜
void fun_floor(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 1; i<src.rows; i++)
for (int j = 1; j < src.cols; j++)
{
int value1 = src.at<Vec3b>(i, j)[0]- src.at<Vec3b>(i-1, j)[0];
//int value2 = src.at<Vec3b>(i, j)[1] - src.at<Vec3b>(i - 1, j)[1];
//int value3 = src.at<Vec3b>(i, j)[2] - src.at<Vec3b>(i - 1, j)[2];
dst.at<Vec3b>(i, j)[0] = value1+128;
dst.at<Vec3b>(i, j)[1] = value1+128;
dst.at<Vec3b>(i, j)[2] = value1+128;
}
return;
}
效果图:
9、素描滤镜
将彩色照片增加一种素描的效果,即:
对图像求灰度图A和底片图B,将灰度图经过高斯滤波之后,和底片图叠加,然后再将像素值较小调整为0。
//素描滤镜
void fun_paint(Mat &src, Mat &dst)
{
dst = src.clone();
cvtColor(src, dst, CV_BGR2GRAY);
Mat gray = dst.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
dst.at<uchar>(i, j) = 255 - dst.at<uchar>(i, j);
}
GaussianBlur(dst, dst, Size(15, 15), 0, 0);
dst = dst + gray;
for (int i = 0; i<src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
if(dst.at<uchar>(i, j)<50)
dst.at<uchar>(i, j) = 0;
}
}
}
效果图:
10、曝光滤镜
将彩色照片增加一种过度曝光的效果,实质上是一种简单的图像增强,即像素值乘以一个系数即可。
b = b+b*1.2;
g = g+g*1.2;
r = r+r*1.2; //1.2可以更改。
//曝光滤镜
void fun_exposure(Mat &src, Mat &dst)
{
dst = src.clone();
for (int i = 0; i<src.rows; i++)
for (int j = 0; j < src.cols; j++)
{
int b = src.at<Vec3b>(i, j)[0];
int g = src.at<Vec3b>(i, j)[1];
int r = src.at<Vec3b>(i, j)[2];
int b_new = b + b*1.2;
int g_new = g + g*1.2;
int r_new = r + r*1.2;
if (b_new > 255) b_new = 255;
if (g_new > 255) g_new = 255;
if (r_new > 255) r_new = 255;
dst.at<Vec3b>(i, j)[0] = b_new;
dst.at<Vec3b>(i, j)[1] = g_new;
dst.at<Vec3b>(i, j)[2] = r_new;
}
return;
}
效果图: