Python向图像添加噪波

2024-03-29 10:10:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python3创建一个图像系统,以便在web应用程序中使用。其思想是从磁盘加载一个图像,并在其中添加一些随机噪声。当我尝试这一点时,我得到的是一个完全随机的图像,与原作不相似:

test1enter image description here

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


Tags: namefrom图像imageimportimgpngrandom
1条回答
网友
1楼 · 发布于 2024-03-29 10:10:51

鉴于所有的新信息,我更新了我的答案与一些调试问题的更多技巧。你知道吗

我发现了一个site here可以创建示例透明图像。我创建了一个64x64青色(R=0,G=255,B=255)的图像,透明层为0.5。我用这个来测试你的代码。你知道吗

cyan image

我在图像中读取了两种比较方法: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保存,因此需要将其转换为正确的顺序,否则图像将具有相反的颜色。例如,当使用反转颜色查看我的青色图像时,显示如下:

cyan reversed (yellow)

您可以使用openCV的color conversion function像这样更改它im = cv2.cvtColor(im, cv2.COLOR_BGRA2RGBA)Here是所有颜色转换代码的列表)。再次,如果需要,请仔细检查图像的大小,自从您将其转换为RGBA后,它仍应具有四个通道。你知道吗

现在可以将噪波添加到图像中。正如您所知,这也会给您的alpha通道添加噪声,随机地使一些像素更透明,而另一些像素更不透明。来自skimage的random_noise function将图像转换为float并将其返回为float。这意味着图像值(通常是0到255之间的整数)将转换为0到1之间的十进制值。您的行img = Image.fromarray(noise_img, 'RGB')不知道如何处理浮点噪声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()看起来像这样(屏幕截图):

s&p cyan image

我使用了PIL库来保存我的图像,而不是openCV,所以它尽可能接近您的代码。你知道吗

fp = 'saved_im.png'
img.save(fp, format="png")

我将图像加载到powerpoint中,以再次检查它在使用此方法保存图像时是否保持了透明度。以下是powerpoint中覆盖在红色圆圈上的已保存图像的屏幕截图:

transparent overlay

相关问题 更多 >