繁体   English   中英

试图让天真的 numpy 图像处理代码更快

[英]Trying to make naive numpy image processing code faster

我正在尝试将包含彩色符号的图像转换为右侧所示的像素艺术(见下图),其中每个彩色符号(占用多个像素)将更改为符号颜色的一个像素。

我正在努力实现的示例

到目前为止,我已经编写了一个非常简单的算法,它只是循环遍历所有像素,而且非常缓慢。 我相信我可以让它更快,例如使用本机 numpy 操作,但我一直无法找到方法。 有小费吗?

(我也开始尝试简单地调整图像大小,但找不到可以使其工作的重采样算法)。

def resize(img, new_width):
    width, height = img.shape[:2]
    new_height = height*new_width//width
    new_image = np.zeros((new_width, new_height,4), dtype=np.uint8)
    x_ratio, y_ratio = width//new_width, height//new_height
    for i in range(new_height):
        for j in range(new_width):
            sub_image = img[i*y_ratio:(i+1)*y_ratio, j*x_ratio:(j+1)*x_ratio]
            found = False
            for row in sub_image:
                for pixel in row:
                    if any(pixel!=[0,0,0,0]):
                        new_image[i,j]=pixel
                        break
                if found:
                    break
    return new_image

一个更大的例子

import cv2
import numpy as np

img=cv2.imread('zjZA8.png')
h,w,c=img.shape
new_img=np.zeros((h//7,w//7,c), dtype='uint8')

for k in range(c):
    for i in range(h//7):
        for j in range(w//7):
            new_img[i,j,k]=np.max(img[7*i:7*i+7,7*j:7*j+7,k])
cv2.imwrite('out3.png', new_img)

在此处输入图像描述 左边是 np.mean 的结果,中心 - 源图像,右边 - np.max 的结果

请测试此代码:

img=cv2.imread('zjZA8.png')
h,w,c=img.shape
bgr=[0,0,0]
bgr[0], bgr[1],bgr[2] =cv2.split(img)
for k in range(3):
    bgr[k].shape=(h*w//7, 7)
    bgr[k]=np.mean(bgr[k], axis=1)
    bgr[k].shape=(h//7, 7, w//7)
    bgr[k]=np.mean(bgr[k], axis=1)
    bgr[k].shape=(h//7,w//7)
    bgr[k]=np.uint8(bgr[k])
out=cv2.merge((bgr[0], bgr[1],bgr[2]))
cv2.imshow('mean_image', out)

修改我的代码以使用本机 np.nonzero 操作就可以了。 我在 1645x1645 图像(new_width=235)上从 ~8s 下降到 ~0.32s,我还尝试在此之上使用 numba。 但开销最终使它变慢。

def resize(img, new_width):
    height, width = img.shape[:2]
    new_height = height*new_width//width
    new_image = np.ones((new_height, new_width,3), dtype=np.uint8)
    x_ratio, y_ratio = width//new_width, height//new_height
    for i in range(new_height):
        for j in range(new_width):
            sub_image = img[i*y_ratio:(i+1)*y_ratio, j*x_ratio:(j+1)*x_ratio]
            non_zero = np.nonzero(sub_image)
            if non_zero[0].size>0:
                new_image[i, j]=sub_image[non_zero[0][0],non_zero[1][0]][:3]
    return new_image

暂无
暂无

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

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