Python. Машинное обучение. Продолжение 2.
Продолжим изучать машинное обучение на Python. На прошлом уроке мы написали модель поиска дефектов. Теперь используя эту модель, найдём дефект и заменим его на нормальный пиксель при помощи модели, разработанной на уроке Python. Машинное обучение. Напомню кратко модель: мы в обучающую выборку загоняем окружения дефектных точек, точнее, цвета тех точек, которые находятся вокруг данной точки. Напомню, что цвет точки – это числа от 0 до 255, для каждой составляющих RGB (Red, Blue, Green). Например, если размер скользящего окна равен 5, то входной элемент состоит из 24 точек (сама эта точке в него не входит). Соответственно, на вход подается 72 числа. На выходе – одно число, это составляющая R, G или B анализируемой точки. Соответственно, нам потребуется три модели машинного обучения, для каждого из цветов RGB, которые мы будет обучать и использовать отдельно.
Итак, вот код программы на Python:
%%time import random import pandas as pd import numpy as np import datetime from sklearn.ensemble import RandomForestClassifier from PIL import Image, ImageDraw #Подключим библиотеки для работы с картинками def CreateModel(selection, out_name): ls=["RY", "GY", "BY"] ls.remove(out_name) Y = selection[out_name] X = selection.drop(ls, axis=1) model = RandomForestClassifier() model.fit(X, Y) return model def GetColor(selection, ls, model): X = selection.drop(ls, axis=1) predicted = model.predict(X) return predicted def ComparePoints(point1, point2): if point1[0]!=point2[0]: return False if point1[1]!=point2[1]: return False if point1[2]!=point2[2]: return False return True #Создаем словарь строки выборки def CreateDicDefected(pix, i, j, W, result=-1): dic={} k=1 for x in range(i-W, i+W+1): for y in range(j-W,j+W+1): if x==i and y==j: continue dic["R"+str(k)] = pix[x, y][0] dic["G"+str(k)] = pix[x, y][1] dic["B"+str(k)] = pix[x, y][2] k=k+1 if result==-1: dic["RY"]=pix[i, j][0] dic["GY"]=pix[i, j][1] dic["BY"]=pix[i, j][2] else: dic["Y"]=result return dic #Создание выборки для поиска дефектов def CreateDefectionSelection(FileOriginal, FileDefected, W): imageOriginal = Image.open(FileOriginal) widthOriginal = imageOriginal.size[0] #Определяем ширину. heightOriginal = imageOriginal.size[1] #Определяем высоту. imageDefected = Image.open(FileDefected) widthDefected = imageDefected.size[0] #Определяем ширину. heightDefected = imageDefected.size[1] #Определяем высоту. pixOriginal = imageOriginal.load() #Выгружаем значения пикселей. pixDefected = imageDefected.load() #Выгружаем значения пикселей. count=widthOriginal*heightOriginal if widthOriginal!=widthDefected: print("Не равна ширина оригинала и испорченной картинки") return NaN if heightOriginal!=heightDefected: print("Не равна высота оригинала и испорченной картинки") return NaN ls=[] for i in range(W,widthOriginal-W): for j in range(W,heightOriginal-W): if ComparePoints(pixOriginal[i,j],pixDefected[i,j]): if random.randint(1,int(count/2000))==1: ls.append(CreateDicDefected(pixOriginal, i, j, W, 1)) else: ls.append(CreateDicDefected(pixDefected, i, j, W, 0)) return pd.DataFrame(ls) def CreateRepairSelection(FileName, W): image = Image.open(FileName) #Открываем изображение. draw = ImageDraw.Draw(image) #Создаем инструмент для рисования. width = image.size[0] #Определяем ширину. height = image.size[1] #Определяем высоту. pix = image.load() #Выгружаем значения пикселей. count=width*height ls_train=[] for i in range(W,width-W): for j in range(W,height-W): if random.randint(1,int(count/2000))==1: dic={} k=1 for x in range(i-W, i+W+1): for y in range(j-W,j+W+1): if x==i and y==j: continue dic["R"+str(k)] = pix[x, y][0] dic["G"+str(k)] = pix[x, y][1] dic["B"+str(k)] = pix[x, y][2] k=k+1 dic["RY"]=pix[i, j][0] dic["GY"]=pix[i, j][1] dic["BY"]=pix[i, j][2] ls_train.append(dic) return ls_train W=2 # Полуразмер окна #Создаем модель дефектов defect=CreateDefectionSelection("d:\\rep\\origtrain.png","d:\\rep\\origtrainspoil.png",W) data_train_defect=pd.DataFrame(defect) Y_defect = data_train_defect["Y"] X_defect = data_train_defect.drop(["Y"], axis=1) model_defect = RandomForestClassifier() model_defect.fit(X_defect,Y_defect) #Создаем модель восстановления rep=CreateRepairSelection("d:\\rep\\origtrainspoil.png",W) data_train_rep=pd.DataFrame(rep) modelR=CreateModel(data_train_rep, "RY") modelG=CreateModel(data_train_rep, "GY") modelB=CreateModel(data_train_rep, "BY") image = Image.open("d:\\rep\\origtestspoild.png") #Открываем изображение. draw = ImageDraw.Draw(image) #Создаем инструмент для рисования. width = image.size[0] #Определяем ширину. height = image.size[1] #Определяем высоту. pix = image.load() #Выгружаем значения пикселей. count=width*height new_image = Image.new("RGB", (width,height), (0,0,0)) draw = ImageDraw.Draw(new_image) # Создаем инструмент для рисования count=1 limit=999999999 ls_defects=[] for i in range(W,width-W): if count>limit: break; for j in range(W,height-W): if count>limit: break; count=count+1 k=1 dic={} for x in range(i-W, i+W+1): for y in range(j-W,j+W+1): if x==i and y==j: continue dic["R"+str(k)] = pix[x, y][0] dic["G"+str(k)] = pix[x, y][1] dic["B"+str(k)] = pix[x, y][2] k=k+1 ls_defects.append(dic) data_test_defects=pd.DataFrame(ls_defects) predicted_defects = model_defect.predict(data_test_defects) print("Построена модель дефектов") #print(predicted_defects) #теперь будем восстанавливать картинку index=0 for i in range(W,width-W): if count>limit: break; for j in range(W,height-W): if count>limit: break; count=count+1 dic={} if predicted_defects[index]>0.5: draw.point((i, j), (pix[i, j][0], pix[i, j][1], pix[i, j][2])) #draw.point((i, j), (255, 255, 255)) else: #draw.point((i, j), (0, 0, 0)) k=1 for x in range(i-W, i+W+1): for y in range(j-W,j+W+1): if x==i and y==j: continue dic["R"+str(k)] = pix[x, y][0] dic["G"+str(k)] = pix[x, y][1] dic["B"+str(k)] = pix[x, y][2] k=k+1 dic["RY"]=pix[i, j][0] dic["GY"]=pix[i, j][1] dic["BY"]=pix[i, j][2] ls_img=[dic] data_img=pd.DataFrame(ls_img) #print(data_img) r = GetColor(data_img,["GY","BY"],modelR) #узнаём значение красного цвета пикселя g = GetColor(data_img,["RY","BY"],modelG) #зелёного b = GetColor(data_img,["RY","GY"],modelB) #синего draw.point((i, j), (r, g, b)) #рисуем пиксель index=index+1 new_image.save("d:\\rep\\restored.png", "PNG") #не забываем сохранить изображение print("Преобразование картинки успешно выполнено")
Теперь смотрим результат работы данной программы:
Как видим, ничего хорошего не получилось. Наоборот, программа сделала еще хуже. Давайте разбираться, почему. На прошлом уроке было сказано, что треть дефектов мы не исправим, и примерно 20% пикселей будут заменены на предсказанные, но только с другой картинки. По сути, так и вышло.
Давайте попробуем заменить дефектные пиксели чёрной точкой, а нормальные белой. Тогда у нас получиться вот что:
Как видим, качество поиска дефектных пикселей очень низкое. Что тут можно сделать? Есть три пути:
- Попробовать обучить на другой картинке, более близкой к исходной.
- Попробовать улучить модель. Например, вместо случайного леса взять другой алгоритм
- По другому сформировать обучающую выборку. Например, загонять в модель другое количество входных точек, или вместо точек использовать что-то другое, например, какие-либо текстурные признаки.
Давайте, для начала, посмотрим, а как этот алгоритм сработает на той картинке, где он обучался:
Как видим, и тут дефекты ищутся некачественно, хотя и лучше, чем на другой картинке. Вангую, картинка тоже не восстановиться, если ее прогнать через алгоритм. Смотрим:
Собственно, так и получилось. Так что первый вариант попробовать другую картинку отпадает, так как даже на самой себе не получается. Осталось еще две идеи: взять другую модель и по другому сформировать выборку. Но это мы сделаем на следующих уроках.
Comments
So empty here ... leave a comment!