python - Python为图像中断PNG添加噪声
问题描述
我正在尝试在 Python 3 中创建一个用于 Web 应用程序的图像系统。这个想法是从磁盘加载图像并为其添加一些随机噪声。当我尝试这个时,我得到一个看起来完全随机的图像,与原始图像不同:
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 透明度),为其添加一些噪音,然后返回它以便它可以由 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
这将弹出一个预噪声图像并返回噪声图像。返回的图像中存在 RGB(和 alpha)问题。
我认为问题是它需要,RGBA
但是当我改变它时,我得到ValueError: buffer is not large enough
解决方案
鉴于所有新信息,我正在更新我的答案,并提供更多调试问题的技巧。
我在这里找到了一个创建示例透明图像的站点。我创建了一个透明层为 0.5 的 64x64 青色(R=0,G=255,B=255)图像。我用它来测试你的代码。
我在图像中阅读了两种比较方法: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 的颜色转换功能im = cv2.cvtColor(im, cv2.COLOR_BGRA2RGBA)
来更改它(这是所有颜色转换代码的列表)。再次,如果需要,请仔细检查图像的大小,因为您将其转换为 RGBA,它仍然应该有四个通道。
您现在可以将噪点添加到图像中。正如您所知,这也会给您的 Alpha 通道添加噪点,随机使一些像素更透明,而另一些像素则更不透明。skimage中的random_noise 函数将您的图像转换为浮点数并将其作为浮点数返回。这意味着图像值(通常是 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中覆盖在红色圆圈上的保存图像的屏幕截图:
推荐阅读
- airflow - 在 Airflow 2.0 中使用 Taskflow API 传递争论
- javascript - 使用 ES6 Javascript 合并两个具有唯一值的数组
- c# - C# - WPF/Xaml - EMGU 显示图像
- c# - 如何在后面的代码中将图像嵌入到 ListView 中?
- docker - 如何修复错误“无法在 unix:///var/run/docker.sock 连接到 Docker 守护进程。docker 守护进程是否正在运行”
- python - @Property - 函数没有被执行 - Python
- c - 如何在 Visual Studio 中使用 C 的 SAL 注释编写此函数?
- angular - Angular Inside ngFor如何设置[禁用]不适用于多个条件
- vue.js - 如果在 router.js vuejs 中条件为真,如何在其他路由上重定向
- sql - 需要有关如何存储数据的建议