我试图通过循环其像素来平滑图像,计算3x3补丁的平均值,然后将平均值应用于此补丁中的所有9个像素。
代码:
import matplotlib.pyplot as plt
import numpy as np
import cv2 as cv
from PIL import Image
# 1. Load Image
name = 'ebay.png'
img = cv.imread(name) #import image
h, w = img.shape[:2]
# 2. Smooth with kernel size 3
for y in range(0, w, 3):
for x in range(0, h, 3):
px1 = img[x][y] #0/0
px2 = img[x][y+1] #0/1
px3 = img[x][y+2] #0/2
px4 = img[x+1][y] #1/0
px5 = img[x+1][y+1] #1/1
px6 = img[x+1][y+2] #1/2
px7 = img[x+2][y] #2/0
px8 = img[x+2][y+1] #2/1
px9 = img[x+2][y+2] #2/2
average = np.average(px1 + px2 + px3 + px4 + px5 + px6 + px7 + px8 + px9)
img[x][y] = average #0/0
img[x][y+1] = average #0/1
img[x][y+2] = average #0/2
img[x+1][y] = average #1/0
img[x+1][y+1] = average #1/1
img[x+1][y+2] = average #1/2
img[x+2][y] = average #2/0
img[x+2][y+1] = average #2/1
img[x+2][y+2] = average #2/2
# 3. Transform the resulting image into pgm format and save result
new_image = Image.fromarray(img)
new_image.save('new.png')
# 4. Show image
new_image.show()
However this just makes my new image just very pixely and not smooth at all.
我假设我在这里做错了什么:
average = np.average(px1 + px2 + px3 + px4 + px5 + px6 + px7 + px8 + px9)
因为,当我使用px5作为平均值时,新图像看起来要好得多(但仍然不是很平滑)。请看下面的图片:
答案 0 :(得分:3)
所以我在这里有两个问题,我能够理解感谢@Ernie Yang和@Cris Luengo。非常感谢你的帮助!
1)我的平均计算问题是它溢出我正在总结像素值。这就是为什么结果看起来很奇怪,因为它缠绕着。所以我不得不改变:
average = np.average(px1 + px2 + px3 + px4 + px5 + px6 + px7 + px8 + px9)
为:
average = px1/9. + px2/9. + px3/9. + px4/9. + px5/9. + px6/9. + px7/9. + px8/9. + px9/9.
2)然而,这并没有使我的图像平滑,因为我只是将平均值分配给补丁中的所有9个像素。所以这导致图像像素化而不是平滑。因此,我不得不将平均值的结果写入中间像素,而不是写入邻域中的所有3x3像素。我还必须将它写入单独的输出图像。您无法在适当的位置执行此操作,因为它会影响后面像素的结果。
更正代码示例:
import matplotlib.pyplot as plt
import numpy as np
import cv2 as cv
from PIL import Image
import scipy.ndimage as ndimage
from scipy.ndimage.filters import gaussian_filter
# 1. Load Image
name = 'ebay.png'
img = cv.imread(name) #import image
h, w = img.shape[:2]
smoothedImage = cv.imread(name) #initialize second image
# 2. Smooth with with kernel size 3
for y in range(0, w-2):
for x in range(0, h-2):
px1 = img[x][y] #0/0
px2 = img[x][y+1] #0/1
px3 = img[x][y+2] #0/2
px4 = img[x+1][y] #1/0
px5 = img[x+1][y+1] #1/1
px6 = img[x+1][y+2] #1/2
px7 = img[x+2][y] #2/0
px8 = img[x+2][y+1] #2/1
px9 = img[x+2][y+2] #2/2
average = px1/9. + px2/9. + px3/9. + px4/9. + px5/9. + px6/9. + px7/9. + px8/9. + px9/9.
smoothedImage[x+1][y+1] = average #1/1
# 3. Transform the resulting image into pgm format and save result
new_image = Image.fromarray(smoothedImage)
new_image.save('new.png')
# 4. Show image
new_image.show()
编辑:
嘿伙计们,我从午睡回来了。 我有很多有趣的想法,现在是我改进的代码:
import matplotlib.pyplot as plt
import numpy as np
import cv2 as cv
from PIL import Image
import scipy.ndimage as ndimage
from scipy.ndimage.filters import gaussian_filter
# 1. Load Image
name = 'ebay.png'
img = cv.imread(name) #import image
h, w = img.shape[:2]
kernel = 5
radius = (kernel-1)/2
img2 = np.zeros((h, w, 3), dtype = 'uint8') #new image to paint on
def pxIsInImgRange(x, y):
if (0<=x) and (x < w):
if (0<=y) and (y < h):
return True
return False
# 2. Smoothing the shit out
for x in range (-radius, w+radius):
for y in range (-radius, h+radius):
if pxIsInImgRange(x,y):
px = 0
for vx2 in range (-radius, radius+1):
for vy2 in range (-radius, radius+1):
x2 = x + vx2
y2 = y + vy2
if pxIsInImgRange(x2,y2):
px = px + (img[y2][x2]/float((kernel*kernel)))
else:
px = px + 0
img2[y][x] = px
# 3. Save image
new_image = Image.fromarray(img2)
new_image.save('new.png')
# 4. Show image
new_image.show()
内核为5的新结果:
答案 1 :(得分:1)
average = np.average(px1 + px2 + px3 + px4 + px5 + px6 + px7 + px8 + px9)
对不平均值的值进行实际求和,
average = (px1 + px2 + px3 + px4 + px5 + px6 + px7 + px8 + px9)/9
应该给你你想要的东西。
另外,对于执行此类任务,scipy.signal.convolve2d是最好的工具。请参阅下面的文档和示例。