怀旧滤镜实现原理
不管是荣耀华为手机还是其他的手机,我们都可以找到相机中的怀旧效果,这是手机中常用的一种滤镜效果。
怀旧风格的设计主要是在图像的颜色空间进行处理。以BGR为例,对B、G、R这3个通道的颜色数值进行处理,让图像有一种泛黄的怀旧效果。设计的转换公式如下:
B=0.272r+0.534g+0.131*b
G=0.349r+0.686g+0.168*b
R=0.393r+0.769g+0.189*b
计算公式中的小写的bgr是原图像的RGB通道的颜色,结果BGR是怀旧变换后的值。需要注意的是,颜色值的范围在[0,255],需要在程序中约束一下。
实现怀旧滤镜
既然我们已经了解了其实现的原理公式。下面我们直接上代码实现该功能,具体代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
def cowboy_effect(img):
new_img = img.copy()
h, w, n = img.shape
for i in range (w):
for j in range (h):
b = img[j, i, 0 ]
g = img[j, i, 1 ]
r = img[j, i, 2 ]
B = int ( 0.272 * r + 0.534 * g + 0.131 * b)
G = int ( 0.349 * r + 0.686 * g + 0.168 * b)
R = int ( 0.393 * r + 0.769 * g + 0.189 * b)
new_img[j, i, 0 ] = max ( 0 , min (B, 255 ))
new_img[j, i, 1 ] = max ( 0 , min (G, 255 ))
new_img[j, i, 2 ] = max ( 0 , min (R, 255 ))
return new_img
if __name__ = = "__main__" :
img = cv2.imread( "48.jpg" )
cv2.imshow( "0" , img)
cv2.imshow( "1" , cowboy_effect(img))
cv2.waitKey()
cv2.destroyAllWindows()
|
运行之后,效果如下:
连环画滤镜原理
从怀旧滤镜就可以看出来,其实相机的各种滤镜效果就是对RGB的颜色通道进行计算处理。既然怀旧滤镜有公式,那么肯定的连环画滤镜也有公式。它的具体公式如下:
R = |g – b + g + r| * r / 256
G = |b – g + b + r| * r / 256
B = |b – g + b + r| * g / 256
实现连环画滤镜
有了公式,下面直接套用公式即可。具体代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 连环画滤镜
def comics_effect(img):
new_img = img.copy()
h, w, n = img.shape
for i in range (w):
for j in range (h):
b = img[j, i, 0 ]
g = img[j, i, 1 ]
r = img[j, i, 2 ]
R = int ( int ( abs (g - b + g + r)) * r / 256 )
G = int ( int ( abs (b - g + b + r)) * r / 256 )
B = int ( int ( abs (b - g + b + r)) * g / 256 )
new_img[j, i, 0 ] = R
new_img[j, i, 1 ] = G
new_img[j, i, 2 ] = B
return new_img
if __name__ = = "__main__" :
img = cv2.imread( "48.jpg" )
cv2.imshow( "0" , img)
cv2.imshow( "1" , comics_effect(img))
cv2.waitKey()
cv2.destroyAllWindows()
|
运行之后,效果如下:
综上所述,基本上所有的基础滤镜都是通过对RGB通道的颜色值进行公式计算得到的。当然,要是数学很好,又对算法情有独钟的读者,可以自己自研滤镜算法丰富滤镜的效果。
熔铸算法
r = r*128/(g+b +1);
g = g*128/(r+b +1);
b = b*128/(g+r +1);
冰冻算法
r = (r-g-b)*3/2;
g = (g-r-b)*3/2;
b = (b-g-r)*3/2;
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
#include <math.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#define MAXSIZE (32768)
using namespace cv;
using namespace std;
void casting(const Mat& src)
{
Mat img;
src.copyTo(img);
int width = src.cols;
int heigh = src.rows;
Mat dst(img.size(),CV_8UC3);
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 + + )
{
float b0 = imgP[ 3 * x];
float g0 = imgP[ 3 * x + 1 ];
float r0 = imgP[ 3 * x + 2 ];
float b = b0 * 255 / (g0 + r0 + 1 );
float g = g0 * 255 / (b0 + r0 + 1 );
float r = r0 * 255 / (g0 + b0 + 1 );
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);
imwrite( "D:/img/熔铸.jpg" ,dst);
}
void freezing(const Mat& src)
{
Mat img;
src.copyTo(img);
int width = src.cols;
int heigh = src.rows;
Mat dst(img.size(),CV_8UC3);
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 + + )
{
float b0 = imgP[ 3 * x];
float g0 = imgP[ 3 * x + 1 ];
float r0 = imgP[ 3 * x + 2 ];
float b = (b0 - g0 - r0) * 3 / 2 ;
float g = (g0 - b0 - r0) * 3 / 2 ;
float r = (r0 - g0 - b0) * 3 / 2 ;
r = (r> 255 ? 255 : (r< 0 ? - r : r));
g = (g> 255 ? 255 : (g< 0 ? - g : g));
b = (b> 255 ? 255 : (b< 0 ? - b : b));
/ / 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;
}
}
imwrite( "D:/img/冰冻.jpg" ,dst);
}
int main()
{
Mat src = imread( "D:/img/scene04.jpg" , 1 );
imshow( "src" ,src);
casting(src);
freezing(src);
waitKey();
}
|
到此这篇关于OpenCV-Python实现怀旧滤镜与连环画滤镜的文章就介绍到这了,更多相关OpenCV 怀旧滤镜与连环画滤镜内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://liyuanjinglyj.blog.csdn.net/article/details/115118465