Эта статья участвует в "Месяце тем Python", подробнее см.Ссылка на мероприятие
Вы чувствуете себя нечетко каждый раз, когда крадете смайлик, и хотите найти более четкую точку?
сначала наблюдайте
- Размытые места - это маленькие черные точки
- Просто удалите маленькие черные точки, и все станет ясно.
Первый взгляд на эффект
| исходное изображение | после ремонта |
|---|---|
Это выглядит хорошо?
думать об идеях
- Как убрать маленькие черные точки и получить каждый пиксель
- Превратите черные точки в белые, и все в порядке
работать
-
Посмотрите на значение каждого пикселя и найдите диапазон маленьких черных точек.
- Диапазон примерно 200-230
-
Найдите цвет глаз и рта, чтобы глаза не побелели
- около 20-140
-
перебирать каждый пиксель
- 200 - 230 Добавить несколько десятков цветов, немного выбелить, не более 255
- 20 - 140 Цвет уменьшится в десятки раз, станет темнее, 0 поставить нельзя, будет слишком темно
-
идеи кода
- читать изображение
- перебирать пиксели
- Рассчитывается дополнительная степень восстановления, отбеливание или чернение
код выше
Возможности кода ограничены, а написание не очень хорошее, если вам интересно, вы можете изучить его.
# !/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()
Код почти готов, давайте посмотрим на эффект, если вы не поняли, вы можете прокомментировать и спросить
Эффект в порядке, он не подходит для пакетов экспрессии со сложными цветами, простые цвета все еще в порядке.