python-3.x - 使用 3x3 卷积核将彩色图像转换为灰度图像
问题描述
我正在编写一个 python 脚本,它将使用 3x3 内核将图像从彩色转换为灰度。
我创建了一个以“图像”和“内核”为参数的函数,并返回图像的灰度版本。在函数内部,我将图像分成 3 个单独的通道:redChannel、greenChannel 和 blueChannel。然后我取这三个渠道的平均值:image = (red + green + blue) / 3
.
我将图像高度和宽度的值存储如下:(Hi, Wi) = image.shape[:2]
并且我对存储内核的高度和宽度做了同样的事情,(Hk, Wk) = kernel.shape[:2]
. 我还包括了图像的填充,这样内核就不会超出边界
pad = (Wk - 1) // 2
。Hi
然后我创建了两个 for 循环,它们将使用和遍历图像的高度和宽度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()
我似乎找不到代码的任何问题,但结果是黑屏。任何帮助将不胜感激))
解决方案
我使用稍微不同的方法找到了答案。此方法获取图像的像素值并将其存储在 3 个颜色通道(R、G、B)中。将res = np.dot(kernel, v)
图像与 3x3 灰度内核相乘。这三个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 > 255:
tr = 255
if tg > 255:
tg = 255
if tb > 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)
推荐阅读
- json - SharePoint 自动更新计算列
- r - 循环程序与其他程序的命令
- c++ - 如何用 Arduino 制作伺服按钮?
- vue.js - vuejs 出现错误“[vuex] 未知操作类型:”
- wordpress - WooCommerce REST API:网关不支持管理员更改订阅的付款方式
- php - 通过ajax使用复选框发送多个数据
- c# - 尝试忽略 Winforms 中的空文本框以过滤 sql 搜索查询
- node.js - Repl.it 监听 EADDRINUSE: 地址已经在使用 :::3001
- javascript - 遍历字典 - JavaScript
- apache-storm - 我们的拓扑在 Storm 2.2.0 中的运行速度明显比在 1.2.0 中慢