【问题标题】:How can I improve color thresholding output?如何提高颜色阈值输出?
【发布时间】:2021-10-17 15:47:51
【问题描述】:

在上面的文章中,他们有以下图片:

而且,他们希望获得如下输出:

我运行了以下脚本:

import cv2

window_name = 'image'

img = cv2.imread("photo.png")

cv2.imshow(window_name, img)
cv2.waitKey(0)


gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.medianBlur(gray, 5)
edges = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9)

cv2.imshow(window_name, edges)
cv2.waitKey(0)

color = cv2.bilateralFilter(img, 9, 250, 250)
cartoon = cv2.bitwise_and(color, color, mask=edges)

cv2.imshow(window_name, cartoon)
cv2.waitKey(0)

首先,脚本很慢。

其次,输出不是他们承诺的:

如何解决这两个问题?

【问题讨论】:

  • 或许可以尝试询问文章的作者?我的猜测是您可能对文章使用了不同尺寸/分辨率的图像,并且参数不太适合您的图像尺寸。至于慢,你有时间写剧本吗?还是它的各个部分?你在什么机器上运行?

标签: python image-processing opencv-python threshold adaptive-threshold


【解决方案1】:

一种简单的方法是在计算摄影部分的非真实感渲染中使用 Python/OpenCV 中的风格化来制作“卡通”。算法参考在https://www.inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf

输入:

import cv2

# read image
img = cv2.imread('beard_man.png')

# use mask with input to do inpainting
result = cv2.stylization(img, sigma_s=50, sigma_r=0.8) 

# write result to disk
cv2.imwrite("beard_man_cartoon.png", result)

# display it
cv2.imshow("RESULT", result)
cv2.waitKey(0)

结果:

【讨论】:

    【解决方案2】:

    简要说明

    我对你的问题很感兴趣,所以我尝试了你建议的网站代码,你发布的代码,我自己用谷歌搜索了一些尝试。甚至与我的同事讨论过,我的教授使用 C# 教授介绍性图像处理/计算机视觉,这是我几年前学习的。

    讨论反馈

    遗憾的是,他们的反应都一样,就像我最初的想法一样,不可能直接转换/转换为您帖子中的第二张图片,发布的第二张图片很可能是艺术图形照片。好吧,也许你更深入地挖掘,也许实际上有一个模块或库可以像第二张图片一样 100% 地转换/转换它。

    示例代码测试

    所以,我开始尝试你发布的网站的内容,在那里剪了一点,调整了一些,但总的来说,与第二张卡通图片相差甚远。

    1. “使用 OpenCV 将图像转换为卡通”的代码和结果
    import cv2
    from matplotlib import pyplot as plt
    
    
    # Reading image
    img = cv2.imread("img.png")
    plt.imshow(img)
    
    # Converting to RGB
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img)
    
    # Detecting edges of the input image
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray = cv2.medianBlur(gray, 9)
    edges = cv2.adaptiveThreshold(
                gray, 255, 
                cv2.ADAPTIVE_THRESH_MEAN_C,
                cv2.THRESH_BINARY, 9, 9
            )
    
    # Cartoonifying the image
    color = cv2.bilateralFilter(img, 9, 250, 250)
    cartoon = cv2.bitwise_and(color, color, mask=edges)
    plt.imshow(cartoon)
    plt.savefig("cartoonify.png")
    plt.show()
    

    1. 继续,然后我在帖子中尝试了您的代码,它实际上产生了一些差异,并且它运行不慢或没有进行任何更改。我运行了你的代码,它确实做了一些改变,代码几乎保持不变,只是在最后添加了保存图像的方法,cv2.imwrite()
    import cv2
    import matplotlib.pyplot as plt
    
    window_name = "image"
    
    img = cv2.imread("img.png")
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray = cv2.medianBlur(gray, 5)
    edges = cv2.adaptiveThreshold(
                gray, 255,
                cv2.ADAPTIVE_THRESH_MEAN_C,
                cv2.THRESH_BINARY,
                9, 9
            )
    
    color = cv2.bilateralFilter(img, 9, 250, 250)
    cartoon = cv2.bitwise_and(color, color, mask=edges)
    
    cv2.imshow(window_name, cartoon)
    cv2.waitKey(0)
    
    cv2.imwrite("cartoon_op.png", cartoon)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    1. 第三个,我在github上搜索,找到了这段代码,但为此我使用了我的stackoverlfow头像,这是一张头像,我想也许白色背景会产生更明显的差异,但事实并非如此,与之前的示例相比,它非常接近。
    import cv2
    import numpy as np
    from tkinter.filedialog import *
    
    photo = askopenfilename()
    img = cv2.imread(photo)
    
    grey = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    grey = cv2.medianBlur(grey, 5)
    edges = cv2.adaptiveThreshold(grey, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9)
    
    #cartoonize
    color = cv2.bilateralFilter(img, 9, 250, 250)
    cartoon = cv2.bitwise_and(color, color, mask = edges)
    
    cv2.imshow("Image", img)
    cv2.imshow("Cartoon", cartoon)
    
    #save
    cv2.imwrite("cartoon-git.png", cartoon)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    1. 就在答案即将结束之前,我发现了这个例子 给出了Dev - How to cartoonize an image with Python 上最接近卡通化图片示例的结果,此示例使用了 Elon 马斯克的照片来演示,虽然是最接近卡通的, 但不知何故,尺寸变得非常小。
    import numpy as np
    import cv2
    
    file_name = "elon.jpg"
    
    def resize_image(image):
        scale_ratio = 0.3
        width = int(image.shape[1] * scale_ratio)
        height = int(image.shape[0] * scale_ratio)
        new_dimensions = (width, height)
        resized = cv2.resize(
                    image, new_dimensions,
                    interpolation=cv2.INTER_AREA
                )
        return resized
    
    def find_countours(image):
        contoured_image = image
        gray = cv2.cvtColor(contoured_image, cv2.COLOR_BGR2GRAY)
        edged = cv2.Canny(gray, 30, 100)
        contours, hierarchy = cv2.findContours(
                                edged, cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_NONE
                            )
        cv2.drawContours(
            contoured_image, contours, 
            contourIdx=-1, color=1,
            thickness=1
        )
        cv2.imshow("Image after contouring", contoured_image)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
        return contoured_image
    
    def color_quantization(image, k=4):
        z = image.reshape((-1, 3))
        z = np.float32(z)
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 
                    10000, 0.0001)
        compactness, label, center = cv2.kmeans(z, k, None, criteria,
                                                1, cv2.KMEANS_RANDOM_CENTERS)
        center = np.uint8(center)
        res = center[label.flatten()]
        res2 = res.reshape((image.shape))
    
        return res2
    
    if __name__ == '__main__':
        
        image = cv2.imread(file_name)
        resized_image = resize_image(image)
        coloured = color_quantization(resized_image)
        contoured = find_countours(coloured)
        final_image = contoured
        save_q = input("Save the image? [y]/[n]: ")
    
        if save_q == "y":
            cv2.imwrite("cartoonized_" + file_name, final_image)
            print("Image saved!")
    

    原始的 Elon.jpg

    卡通化的 Elon.jpg

    总结

    我希望这个听起来没有明确答案的冗长答案会有所帮助,这正是我发现感兴趣并决定分享发现它的过程。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-01
      • 2016-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-06
      • 2019-01-20
      • 1970-01-01
      相关资源
      最近更新 更多