Python 为图像中断 PNG 添加噪声
Python add noise to image breaks PNG
我正在尝试在 Python 3 中创建一个图像系统以用于网络应用程序。这个想法是从磁盘加载图像并向其添加一些随机噪声。当我尝试这个时,我得到了一张看起来完全随机的图像,与原始图像不同:
import cv2
import numpy as np
from skimage.util import random_noise
from random import randint
from pathlib import Path
from PIL import Image
import io
image_files = [
{
'name': 'test1',
'file': 'test1.png'
},
{
'name': 'test2',
'file': 'test2.png'
}
]
def gen_image():
rand_image = randint(0, len(image_files)-1)
image_file = image_files[rand_image]['file']
image_name = image_files[rand_image]['name']
image_path = str(Path().absolute())+'/img/'+image_file
img = cv2.imread(image_path)
noise_img = random_noise(img, mode='s&p', amount=0.1)
img = Image.fromarray(noise_img, 'RGB')
fp = io.BytesIO()
img.save(fp, format="PNG")
content = fp.getvalue()
return content
gen_image()
我也试过使用pypng:
import png
# Added the following to gen_image()
content = png.from_array(noise_img, mode='L;1')
content.save('image.png')
我如何从磁盘加载 png(具有 alpha 透明度),向其添加一些噪声,然后 return 以便它可以通过 Web 服务器代码(flask、aiohttp 等)显示。
如 makayla 的回答所示,这使它变得更好:noise_img = (noise_img*255).astype(np.uint8)
但是颜色仍然错误并且没有透明度。
这是更新后的函数:
def gen_image():
rand_image = randint(0, len(image_files)-1)
image_file = image_files[rand_image]['file']
image_name = image_files[rand_image]['name']
image_path = str(Path().absolute())+'/img/'+image_file
img = cv2.imread(image_path)
cv2.imshow('dst_rt', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Problem exists somewhere below this line.
img = random_noise(img, mode='s&p', amount=0.1)
img = (img*255).astype(np.uint8)
img = Image.fromarray(img, 'RGB')
fp = io.BytesIO()
img.save(fp, format="png")
content = fp.getvalue()
return content
这将弹出预噪声图像和 return 噪声图像。 returned 图像中存在 RGB(和 alpha)问题。
我认为问题是它需要 RGBA
但是当我更改为那个时,我得到 ValueError: buffer is not large enough
鉴于所有新信息,我正在更新我的答案,提供更多调试问题的技巧。
我找到了一个 site here 可以创建示例透明图像。我创建了一个 64x64 青色(R=0,G=255,B=255)图像,透明度层为 0.5。我用它来测试你的代码。
我在图片中读到两种比较方式:im1 = cv2.imread(fileName)
和im2 = cv2.imread(fileName,cv2.IMREAD_UNCHANGED)
。 np.shape(im1)
返回 (64,64,3)
,np.shape(im2)
返回 (64,64,4)
。这就是为什么需要该标志的原因——opencv 中的默认 imread 设置将读入透明图像作为普通 RGB 图像。
但是 opencv 读取的是 BGR 而不是 RGB,并且由于您无法使用 opencv 保存,因此您需要将其转换为正确的顺序,否则图像将出现反色。例如,我的青色图像,当用反转颜色查看时显示如下:
您可以使用 openCV 更改它 color conversion function like this im = cv2.cvtColor(im, cv2.COLOR_BGRA2RGBA)
(Here 是所有颜色转换代码的列表)。再次,如果需要,请仔细检查图像的大小,因为您将其转换为 RGBA,它应该仍然有四个通道。
您现在可以为图像添加噪点。 如你所知,这也会给你的 alpha 通道增加噪音,随机地使一些像素更透明而其他的不那么透明。 来自 skimage 的 random_noise function 转换你的图像浮动和 returns 它作为浮动。这意味着图像值(通常是从 0 到 255 的整数)将转换为从 0 到 1 的十进制值。您的行 img = Image.fromarray(noise_img, 'RGB')
不知道如何处理浮点数 noise_img。这就是为什么图像在您保存时以及我尝试显示它时都乱七八糟的原因。
所以我拍摄了我的青色图像,添加了噪声,然后将浮点数转换回 8 位。
noise_img = random_noise(im, mode='s&p', amount=0.1)
noise_img = (noise_img*255).astype(np.uint8)
img = Image.fromarray(noise_img, 'RGBA')
现在看起来像这样(截图)使用 img.show()
:
我使用 PIL 库而不是 openCV 来保存我的图像,因此它尽可能接近您的代码。
fp = 'saved_im.png'
img.save(fp, format="png")
我将图像加载到 powerpoint 中,以便在使用此方法保存图像时仔细检查它是否保留了透明度。这是在 powerpoint 中覆盖在红色圆圈上的已保存图像的屏幕截图:
我正在尝试在 Python 3 中创建一个图像系统以用于网络应用程序。这个想法是从磁盘加载图像并向其添加一些随机噪声。当我尝试这个时,我得到了一张看起来完全随机的图像,与原始图像不同:
import cv2
import numpy as np
from skimage.util import random_noise
from random import randint
from pathlib import Path
from PIL import Image
import io
image_files = [
{
'name': 'test1',
'file': 'test1.png'
},
{
'name': 'test2',
'file': 'test2.png'
}
]
def gen_image():
rand_image = randint(0, len(image_files)-1)
image_file = image_files[rand_image]['file']
image_name = image_files[rand_image]['name']
image_path = str(Path().absolute())+'/img/'+image_file
img = cv2.imread(image_path)
noise_img = random_noise(img, mode='s&p', amount=0.1)
img = Image.fromarray(noise_img, 'RGB')
fp = io.BytesIO()
img.save(fp, format="PNG")
content = fp.getvalue()
return content
gen_image()
我也试过使用pypng:
import png
# Added the following to gen_image()
content = png.from_array(noise_img, mode='L;1')
content.save('image.png')
我如何从磁盘加载 png(具有 alpha 透明度),向其添加一些噪声,然后 return 以便它可以通过 Web 服务器代码(flask、aiohttp 等)显示。
如 makayla 的回答所示,这使它变得更好:noise_img = (noise_img*255).astype(np.uint8)
但是颜色仍然错误并且没有透明度。
这是更新后的函数:
def gen_image():
rand_image = randint(0, len(image_files)-1)
image_file = image_files[rand_image]['file']
image_name = image_files[rand_image]['name']
image_path = str(Path().absolute())+'/img/'+image_file
img = cv2.imread(image_path)
cv2.imshow('dst_rt', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# Problem exists somewhere below this line.
img = random_noise(img, mode='s&p', amount=0.1)
img = (img*255).astype(np.uint8)
img = Image.fromarray(img, 'RGB')
fp = io.BytesIO()
img.save(fp, format="png")
content = fp.getvalue()
return content
这将弹出预噪声图像和 return 噪声图像。 returned 图像中存在 RGB(和 alpha)问题。
我认为问题是它需要 RGBA
但是当我更改为那个时,我得到 ValueError: buffer is not large enough
鉴于所有新信息,我正在更新我的答案,提供更多调试问题的技巧。
我找到了一个 site here 可以创建示例透明图像。我创建了一个 64x64 青色(R=0,G=255,B=255)图像,透明度层为 0.5。我用它来测试你的代码。
我在图片中读到两种比较方式:im1 = cv2.imread(fileName)
和im2 = cv2.imread(fileName,cv2.IMREAD_UNCHANGED)
。 np.shape(im1)
返回 (64,64,3)
,np.shape(im2)
返回 (64,64,4)
。这就是为什么需要该标志的原因——opencv 中的默认 imread 设置将读入透明图像作为普通 RGB 图像。
但是 opencv 读取的是 BGR 而不是 RGB,并且由于您无法使用 opencv 保存,因此您需要将其转换为正确的顺序,否则图像将出现反色。例如,我的青色图像,当用反转颜色查看时显示如下:
您可以使用 openCV 更改它 color conversion function like this im = cv2.cvtColor(im, cv2.COLOR_BGRA2RGBA)
(Here 是所有颜色转换代码的列表)。再次,如果需要,请仔细检查图像的大小,因为您将其转换为 RGBA,它应该仍然有四个通道。
您现在可以为图像添加噪点。 如你所知,这也会给你的 alpha 通道增加噪音,随机地使一些像素更透明而其他的不那么透明。 来自 skimage 的 random_noise function 转换你的图像浮动和 returns 它作为浮动。这意味着图像值(通常是从 0 到 255 的整数)将转换为从 0 到 1 的十进制值。您的行 img = Image.fromarray(noise_img, 'RGB')
不知道如何处理浮点数 noise_img。这就是为什么图像在您保存时以及我尝试显示它时都乱七八糟的原因。
所以我拍摄了我的青色图像,添加了噪声,然后将浮点数转换回 8 位。
noise_img = random_noise(im, mode='s&p', amount=0.1)
noise_img = (noise_img*255).astype(np.uint8)
img = Image.fromarray(noise_img, 'RGBA')
现在看起来像这样(截图)使用 img.show()
:
我使用 PIL 库而不是 openCV 来保存我的图像,因此它尽可能接近您的代码。
fp = 'saved_im.png'
img.save(fp, format="png")
我将图像加载到 powerpoint 中,以便在使用此方法保存图像时仔细检查它是否保留了透明度。这是在 powerpoint 中覆盖在红色圆圈上的已保存图像的屏幕截图: