几十行代码,修复马赛克表情包|Python 主题月

本文正在参加「Python主题月」,详情查看活动链接

是不是每次偷表情包时,都感觉模糊感, 想找一个清楚点

先观察

  1. 模糊的地方就是有些小黑色点
  2. 只需去掉小黑点,就清楚了

先看下效果

原图 修复后
src=http___5b0988e595225.cdn.sohucs.com_images_20190705_099f2e9f3718465aa3ec54bd94410558.jpeg&refer=http___5b0988e595225.cdn.sohucs.jpeg repair-929ef834-c0ac-483f-81b4-9db25598d85a.png
WX20210513-112540@2x.png repair-9cd7d9ff-c567-4f66-be6a-4102b540a862.png

是不是看着还不错

想思路

  1. 如何去掉小黑点,拿到每个像素点
  2. 将小黑点变成白色的就OK了

去操作

  1. 观察每个像素值,找到小黑点的范围
* 范围大概在 200 - 230
![image.png](https://gitee.com/songjianzaina/juejin_p8/raw/master/img/288cdfffc5f6aecbc3250464b5d4ef5bddf03cae6243c1f20ce609b6db4b38cd)
  1. 找到眼睛、嘴 的颜色,防止吧眼也变白了
* 大概在 20-140
![image.png](https://gitee.com/songjianzaina/juejin_p8/raw/master/img/b9cee24504856940a1fe828b4c7861802e7a2306791dae57fe737e93307cbfcd)
  1. 遍历每个像素点
* 200 - 230 颜色加几十,变白一些,不能超过255
* 20 - 140 颜色减几十,变黑一些,不能设置0,会太黑了
  1. 代码思路
* 读取图片
* 遍历像素点
* 更具修复程度算出,变白或变黑

上代码

代码能力有限,写的不咋地,有兴趣可以研究一下

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
python复制代码# !/usr/bin/python3
import threading
import uuid
from tkinter import *
from tkinter import filedialog, messagebox

import cv2
from PIL import ImageTk, Image


class MY_GUI():

def __init__(self, init_window_name):
self.init_window_name = init_window_name
self.out_frame = None
self.in_frame = None

# 绘制窗口
def set_init_window(self):
self.init_window_name.title("图片处理") # 窗口名
self.init_window_name.geometry('950x681+10+10')

self.input_label = Label(self.init_window_name, text="路径:")
self.input_label.place(x=0, y=0, width=80, height=30)
self.input_path = Entry(self.init_window_name)
self.input_path.place(x=80, y=0, width=850, height=30)

self.init_data_label = Label(self.init_window_name, text="修复前")
self.init_data_label.place(x=0, y=60, width=80, height=30)
self.result_data_label = Label(self.init_window_name, text="修复后")
self.result_data_label.place(x=550, y=60, width=80, height=30)

self.in_img_button = Button(self.init_window_name, text="选择图片", bg="lightblue", width=10,
command=self.select_in_frame)
self.in_img_button.place(x=400, y=100, width=150, height=30)

self.degree_label = Label(self.init_window_name, text="修复程度(1-10)")
self.degree_label.place(x=400, y=150, width=150, height=30)
self.degree_input = Spinbox(self.init_window_name, from_=1, to=10) # 调用内部方法 加()为直接调用
self.degree_input.place(x=400, y=180, width=150, height=30)

self.repair_button = Button(self.init_window_name, text="修复", bg="lightblue", width=10,
command=self.access_pixels)
self.repair_button.place(x=400, y=230, width=150, height=30)
self.d_img_button = Button(self.init_window_name, text="保存", bg="lightblue", width=10,
command=self.d_img)
self.d_img_button.place(x=400, y=280, width=150, height=30)

def select_in_frame(self):
path = filedialog.askopenfilename()
if path is None or path == '':
messagebox.showinfo("提示", "请选择图片")
return
self.input_path.delete(0, END)
self.input_path.insert(0, path)
frame = cv2.imread(path)
self.in_frame = frame

# 这里就修复图片的代码了
def access_pixels(self):
if self.in_frame is None:
messagebox.showinfo("提示", "请选择图片")
return
degreeStr = self.degree_input.get()
if degreeStr is None or degreeStr == '':
degreeStr = '0'

degree = int(degreeStr)
if degree < 1:
degree = 1
elif degree > 10:
degree = 10

frame = self.in_frame.copy()

print(frame.shape) # shape内包含三个元素:按顺序为高、宽、通道数
height = frame.shape[0]
weight = frame.shape[1]
channels = frame.shape[2]

showImgHeight = int(height / (weight / 400))
# 这里是转换rgb 不然 保存下来会变色
b1, g1, r1 = cv2.split(self.in_frame.copy())
rgb_img1 = cv2.merge([r1, g1, b1])
im = Image.fromarray(cv2.resize(rgb_img1, (400, showImgHeight)))
imgtk = ImageTk.PhotoImage(image=im)

self.before2_img = Label(self.init_window_name, image=imgtk).place(x=0, y=90, width=400,
height=showImgHeight)
print("weight : %s, height : %s, channel : %s" % (weight, height, channels))
for row in range(height): # 遍历高
for col in range(weight): # 遍历宽
for c in range(channels): # 便利通道
pv = frame[row, col, c]
# 这里是判断是不是小黑点
if pv > 23 * (11 - degree):
# 这里就是计算增加白色 原颜色+修复程度*10,防止太白 颜色都一样
if (pv + degree * 10) > 255:
frame[row, col, c] = 255
else:
frame[row, col, c] = (pv + degree * 10)
# 这里是判断黑色,是不是需要更黑一些
if pv < degree * 15:
frame[row, col, c] = 0

self.out_frame = frame
b, g, r = cv2.split(self.out_frame.copy())
rgb_img = cv2.merge([r, g, b])
im2 = Image.fromarray(cv2.resize(rgb_img, (400, showImgHeight)))
imgtk2 = ImageTk.PhotoImage(image=im2)
self.img2 = Label(self.init_window_name, image=imgtk2).place(x=550, y=90, width=400, height=showImgHeight)
self.img2.place()

def d_img(self):
if self.out_frame is None:
messagebox.showinfo("提示", "请先修复图片")
return
path = filedialog.askdirectory()
if path is None or path == '':
messagebox.showinfo("提示", "请选择输出路径")
return
savepath = path + "/repair-" + str(uuid.uuid4()) + ".png"
cv2.imwrite(savepath, self.out_frame)


if __name__ == '__main__':
init_window = Tk()
ZMJ_PORTAL = MY_GUI(init_window)
ZMJ_PORTAL.set_init_window()
init_window.mainloop()

代码差不多了,看看效果吧,有不懂的可以评论问

j1.png

j2.png

j3.png

效果还行,不适用于颜色复杂的表情包, 简单的颜色还是可以的

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%