如何使用OpenCV生成类似纸张的背景

9

我正在尝试使用OpenCV实现随机的纸张背景。

附上的示例展示了真实的纸质文档痕迹(请忽略上面的手写内容)。 enter image description here

只需应用噪声即可轻松实现原始纸张的简单效果。

import cv2
import numpy as np

BG_COLOR = 209

def blank_image(width=1024, height=1024):
    img = np.full((height, width, 1), BG_COLOR, np.uint8)
    return img

def noisy(image):
    row, col, ch = image.shape
    mean = 0
    sigma = 10
    gauss = np.random.normal(mean, sigma, (row, col, ch))
    gauss = gauss.reshape(row, col, ch)
    noisy = gauss + image
    return noisy

if __name__ == '__main__':
    img = blank_image()
    cv2.imwrite('out.jpg', noisy(img))

但是如果没有上面的图案,它看起来太均匀了:

enter image description here

我想知道从第一张图片中生成这样随机结构的最佳方法是什么。


1
人们好奇的地方就会有实验发生。创建一些随机坐标,应用一些模糊效果,也许创建一些非常轻量级的“污渍”印章并应用它们。用较暗(或较浅)的线连接2个坐标以形成褶皱。将模糊效果应用于较靠近边缘的位置(手脏的位置)。发挥创意。这些都不值得在Stack Overflow上发问,所以投票关闭为“必然导致讨论”。如果您的实验代码失败,请回来。这可能更适合某种“艺术”论坛。 - Patrick Artner
1
还有一个提示,如果你有GIMP2 - 它有脚本过滤器,我猜应该可以创建“纸张般”的纹理。检查它的图层(或窃取部分),并将其作为半透明PNG应用于您的图片 - 也许还可以使用杯子上的污渍; o) - Patrick Artner
你的任务是一个计算机图形学问题。 OpenCV 更多关注于计算机视觉。 - Micka
1
请查看过程噪声纹理及相关主题。 - Micka
2
我得到的第一个谷歌搜索结果是 https://lodev.org/cgtutor/randomnoise.html。 - BoboDarph
显示剩余6条评论
1个回答

10
受BoboDarph方案的启发,我制作了一种类似纸张的质感。现在,我需要添加来自上面真实照片的艺术品。
以下是代码:
import cv2
import numpy as np


BG_COLOR = 209
BG_SIGMA = 5
MONOCHROME = 1


def blank_image(width=1024, height=1024, background=BG_COLOR):
    """
    It creates a blank image of the given background color
    """
    img = np.full((height, width, MONOCHROME), background, np.uint8)
    return img


def add_noise(img, sigma=BG_SIGMA):
    """
    Adds noise to the existing image
    """
    width, height, ch = img.shape
    n = noise(width, height, sigma=sigma)
    img = img + n
    return img.clip(0, 255)


def noise(width, height, ratio=1, sigma=BG_SIGMA):
    """
    The function generates an image, filled with gaussian nose. If ratio parameter is specified,
    noise will be generated for a lesser image and then it will be upscaled to the original size.
    In that case noise will generate larger square patterns. To avoid multiple lines, the upscale
    uses interpolation.

    :param ratio: the size of generated noise "pixels"
    :param sigma: defines bounds of noise fluctuations
    """
    mean = 0
    assert width % ratio == 0, "Can't scale image with of size {} and ratio {}".format(width, ratio)
    assert height % ratio == 0, "Can't scale image with of size {} and ratio {}".format(height, ratio)

    h = int(height / ratio)
    w = int(width / ratio)

    result = np.random.normal(mean, sigma, (w, h, MONOCHROME))
    if ratio > 1:
        result = cv2.resize(result, dsize=(width, height), interpolation=cv2.INTER_LINEAR)
    return result.reshape((width, height, MONOCHROME))


def texture(image, sigma=BG_SIGMA, turbulence=2):
    """
    Consequently applies noise patterns to the original image from big to small.

    sigma: defines bounds of noise fluctuations
    turbulence: defines how quickly big patterns will be replaced with the small ones. The lower
    value - the more iterations will be performed during texture generation.
    """
    result = image.astype(float)
    cols, rows, ch = image.shape
    ratio = cols
    while not ratio == 1:
        result += noise(cols, rows, ratio, sigma=sigma)
        ratio = (ratio // turbulence) or 1
    cut = np.clip(result, 0, 255)
    return cut.astype(np.uint8)


if __name__ == '__main__':
    cv2.imwrite('texture.jpg', texture(blank_image(background=230), sigma=4, turbulence=4))
    cv2.imwrite('texture-and-noise.jpg', add_noise(texture(blank_image(background=230), sigma=4), sigma=10))

    cv2.imwrite('noise.jpg', add_noise(blank_image(1024, 1024), sigma=10))

生成的图片: 这里输入图片描述

你添加了构件吗? - Jeru Luke
@JeruLuke,目前我还没有想到如何添加图像边缘和黑色背景。 - ZAN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接