Преобразование цветного изображения в оттенки серого с использованием ядра свертки 3×3

#python-3.x #numpy #convolution #opencv-python

Вопрос:

Я пишу скрипт на python, который будет использовать ядро 3×3 для преобразования изображения из цветного в оттенки серого.

Я создал функцию, которая принимает «изображение» и «ядро» в качестве параметров и возвращает версию изображения в оттенках серого. Внутри функции я разделил изображение на 3 отдельных канала: красный канал, зеленый канал и синий канал. Затем я беру среднее значение этих трех каналов как таковое: image = (red green blue) / 3 .

Я сохранил значения высоты и ширины изображения следующим образом: (Hi, Wi) = image.shape[:2] и я сделал то же самое для хранения высоты и ширины ядра, (Hk, Wk) = kernel.shape[:2] . Я также включил заполнение для изображения, чтобы ядро не выходило за рамки pad = (Wk - 1) // 2 . Затем я создал два цикла for, которые будут повторяться по высоте и ширине изображения, используя Hi и Wi . Внутри циклов for я изменил изображение так, чтобы я мог умножить его с помощью ядра. Затем я сохраняю вычисленный результат в выходном массиве.

Это полный код:

 from skimage.exposure import rescale_intensity import numpy as np import cv2  def convolve(image, kernel):  (Hi, Wi) = image.shape[:2]  (Hk, Wk) = kernel.shape[:2]   red, green, blue = cv2.split(image)  image = (red   green   blue) / 3   pad = (Wk - 1) // 2  image = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REPLICATE)  output = np.zeros((Hi, Wi), dtype="float32")   for y in range(Hi, Hk   pad):  for x in range(Wi, Wk   pad):  roi = image[y - pad:y   pad   1, x - pad:x   pad   1]  k = (roi * kernel).sum()  output[y - pad, x - pad] = k  output = rescale_intensity(output, in_range=(0, 255))  output = (output * 255).astype("uint8")  return output   image = cv2.imread("mandrill.png")  kernel = np.ones((3, 3)) * (1/3)  cv2.imshow("Output", convolve(image, kernel)) cv2.waitKey(0) cv2.destroyAllWindows()  

Кажется, я не могу найти никаких проблем с кодом, но в результате появляется черный экран. Любая помощь будет очень признательна))

Комментарии:

1. Пожалуйста, добавьте решение в поле для ответов

Ответ №1:

Я нашел ответ, используя несколько иной подход. Этот метод получает значения пикселей изображения и сохраняет их в 3 цветовых каналах (R,G,B). Изображение res = np.dot(kernel, v) умножается на ядро в оттенках серого 3×3. Эти три if statements масштабируют интенсивность значений пикселей.

 import matplotlib.pyplot as plt from PIL import Image import numpy as np  def convolve(img, kernel):  width, height = img.size  pixels = img.load()   for py in range(height):  for px in range(width):  r, g, b = img.getpixel((px, py))   v = np.array([[r], [g], [b]])  res = np.dot(kernel, v)   tr, tg, tb = int(res[0, 0]), int(res[1, 0]), int(res[2, 0])   if tr gt; 255:  tr = 255   if tg gt; 255:  tg = 255   if tb gt; 255:  tb = 255   pixels[px, py] = (tr, tg, tb)   return img  img = Image.open('mandrill.jpg') grayscale = np.ones((3, 3)) * (1/3)  convolve(img, grayscale) plt.imshow(img)