简体   繁体   English

如何提高颜色阈值输出?

[英]How can I improve color thresholding output?

In the above article they have the following image:在上面的文章中,他们有以下图片:

在此处输入图片说明

And, they wanted to obtain an output like the following:而且,他们想要获得如下输出:

在此处输入图片说明

I ran the following script:我运行了以下脚本:

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)

Firstly, the script is very slow.首先,脚本非常慢。

Secondly, the output is not what they promised would be:其次,输出不是他们承诺的那样:

在此处输入图片说明

How can I fix these two issues?我该如何解决这两个问题?

One simple approach is to use stylization in Python/OpenCV in the Non-Photorealistic Rendering in the Computational Photography section to make a "cartoon".一种简单的方法是在计算摄影部分的非真实感渲染中使用 Python/OpenCV 中的风格化来制作“卡通”。 Reference to algorithm is at https://www.inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf算法参考在https://www.inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf

Input:输入:

在此处输入图片说明

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)

Result:结果:

在此处输入图片说明

Brief description简要描述;简介

I'm so interested in your question, so I tried your suggested website's code, the code you posted, and myself googled a few to tried.我对你的问题很感兴趣,所以我尝试了你推荐的网站代码,你发布的代码,我自己在谷歌上搜索了一些尝试。 Even discussed with my peers, my professor who taught introductory image processing/computer vision using C# that I took couple years ago.甚至与我的同龄人讨论过,我的教授使用 C# 教授介绍性的图像处理/计算机视觉,这是我几年前学习的。

Discussion feedback讨论反馈

Sadly they all respond the same and like what I initially thought, it's not possible to transform/convert directly into the second picture in your post, the posted second picture is most likely to be an artistic graphics photo.可悲的是,他们的反应都是一样的,就像我最初想的那样,不可能直接转换/转换为您帖子中的第二张图片,发布的第二张图片很可能是一张艺术图形照片。 Well, maybe you dig deeper maybe there's actually a module or library that can actually transform/convert it 100% like the second picture.好吧,也许您深入挖掘,也许实际上有一个模块或库可以像第二张图片那样 100% 转换/转换它。

Examples code testing示例代码测试

So, I begin trying out the contents of your posted website, snipped a bit there, adjusted some, but overall, no where near to the second cartoon picture.所以,我开始尝试你发布的网站的内容,在那里剪了一点,调整了一些,但总的来说,与第二张卡通图片相去甚远。

  1. The code and result of "Converting An Image To A Cartoon Using OpenCV" “Converting An Image To A Cartoon Using 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()

“使用 OpenCV 将图像转换为卡通”的结果

  1. Moving on, then I tried your code in the post, and it's actually made some differences, and it doesn't run slow or didn't make changes.继续,然后我在帖子中尝试了您的代码,它实际上产生了一些差异,并且它不会运行缓慢或没有进行更改。 I ran your code, and it did made some change, the code stays pretty much the same, just added saving image methods at the end, cv2.imwrite() .我运行了你的代码,它确实做了一些改变,代码几乎保持不变,只是在最后添加了保存图像方法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. The third, I searched on github , found this code, but for this I used my stackoverlfow profile picture, which it's a headshot, I thought maybe the white background would make more visible difference, but it didn't, compared to previous examples, it's pretty much close.第三,我在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. Just before almost finished with the answer, I found this example gives the closest result of cartoonized picture example on Dev - How to cartoonize an image with Python , this example used Elon Musk's photo to demonstrate, although it's the closest to cartoon, but the size somehow just got really small.就在快答完之前,我发现这个例子给出了Dev - How to cartoonize an image with Python上最接近卡通化图片示例的结果,这个例子使用了 Elon Musk 的照片来演示,虽然它最接近卡通,但是尺寸不知何故变得非常小。
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!")

Original Elon.jpg原版 Elon.jpg

原版elon.jpg

Cartoonized Elon.jpg卡通化 Elon.jpg

Elon-必须-卡通化

Wrapping up包起来

I hope this long answer that sounded like no definitive answer helps, it's just what I found interested and decided to share the process of discovering it.我希望这个听起来没有明确答案的长答案有帮助,这正是我感兴趣的内容,并决定分享发现它的过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM