簡體   English   中英

OpenCV - 拆分和合並阿爾法通道很慢

[英]OpenCV - Splitting and merging alpha channels slow

我正在使用 Python OpenCV 來分割通道並像這樣刪除黑色背景......

    b_channel, g_channel, r_channel = cv2.split(image_1)
    alpha_channel = np.zeros_like(gray)

    for p in range(alpha_channel.shape[0]):
        for q in range(alpha_channel.shape[1]):
            if b_channel[p][q]!=0 or g_channel[p][q]!=0 or r_channel[p][q]!=0:
                alpha_channel[p][q] = 255

    merged = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))

這是可行的,但在僅 200kb 的圖像上完成大約需要 10 秒

有沒有更有效的方法來做到這一點,或者我可以使用我擁有的代碼獲得一些速度提升?

使用for循環遍歷像素實際上非常緩慢且效率低下。 另外,根據此處的文檔,

cv2.split()是一項昂貴的操作(就時間而言)。 因此,僅在需要時才這樣做。 否則請進行Numpy索引。

您可以嘗試使用numpy進行矢量化和索引編制,如下所示:

# create the image with alpha channel
img_rgba = cv2.cvtColor(img, cv2.COLOR_RGB2RGBA)

# mask: elements are True any of the pixel value is 0         
mask = (img[:, :, 0:3] != [0,0,0]).any(2) 
#assign the mask to the last channel of the image
img_rgba[:,:,3]  = (mask*255).astype(np.uint8)

對於您正在做的事情,使用cv2.bitwise_or似乎是最快的方法:

image_1 = img
# your method
start_time = time.time()
b_channel, g_channel, r_channel = cv2.split(image_1)
alpha_channel = np.zeros_like(gray)
for p in range(alpha_channel.shape[0]):
    for q in range(alpha_channel.shape[1]):
        if b_channel[p][q]!=0 or g_channel[p][q]!=0 or r_channel[p][q]!=0:
            alpha_channel[p][q] = 255
elapsed_time = time.time() - start_time
print('for cycles:  ' + str(elapsed_time*1000.0) + ' milliseconds')

# my method
start_time = time.time()
b_channel, g_channel, r_channel = cv2.split(image_1)
alpha_channel2 = cv2.bitwise_or(g_channel,r_channel)
alpha_channel2 =  cv2.bitwise_or(alpha_channel2, b_channel)
_,alpha_channel2 = cv2.threshold(alpha_channel2,0,255,cv2.THRESH_BINARY)
elapsed_time2 = time.time() - start_time
print('bitwise + threshold:  '+ str(elapsed_time2*1000.0) + ' milliseconds')

# annubhav's method
start_time = time.time()
img_rgba = cv2.cvtColor(image_1, cv2.COLOR_RGB2RGBA)
# mask: elements are True any of the pixel value is 0         
mask = (img[:, :, 0:3] != [0,0,0]).any(2) 
#assign the mask to the last channel of the image
img_rgba[:,:,3]  = (mask*255).astype(np.uint8)
elapsed_time3 = time.time() - start_time
print('anubhav:  ' + str(elapsed_time3*1000.0) + ' milliseconds')

周期:2146.300792694092毫秒

按位+閾值:4.959583282470703毫秒

anubhav:27.924776077270508毫秒

最快的解決方案

讓我們考慮一個使用cv2.split的函數,我們知道它的效率非常低,我們可以繼續調整或裁剪圖像的某個部分,然后對其進行計算。 在我必須使用cv2.split計算圖像的色彩度的情況下,我繼續調整大小並裁剪圖像以使cv2.split工作。

  • 可以通過Resizing進行更快更合理cv2.split計算

代碼

def image_colorfulness(self,image):
        # split the image into its respective RGB components
        (B, G, R) = cv2.split(image.astype("float"))
        print(f'Split Image to B G R {(B, G, R)}')
        # compute rg = R - G
        rg = np.absolute(R - G)
        print(f'Computed RG to {rg}')
        # compute yb = 0.5 * (R + G) - B
        yb = np.absolute(0.5 * (R + G) - B)
        # compute the mean and standard deviation of both `rg` and `yb`
        print('Performing Absolute')
        (rbMean, rbStd) = (np.mean(rg), np.std(rg))
        (ybMean, ybStd) = (np.mean(yb), np.std(yb))
        # combine the mean and standard deviations
        print('Performing Standard Deviation')
        stdRoot = np.sqrt((rbStd ** 2) + (ybStd ** 2))
        meanRoot = np.sqrt((rbMean ** 2) + (ybMean ** 2))
        # derive the "colorfulness" metric and return it
        return stdRoot + (0.3 * meanRoot)


def crop_square(self, img, size, interpolation=cv2.INTER_AREA):
        h, w = img.shape[:2]
        min_size = np.amin([h,w])

        # Centralize and crop
        crop_img = img[int(h/2-min_size/2):int(h/2+min_size/2), int(w/2-min_size/2):int(w/2+min_size/2)]
        resized = cv2.resize(crop_img, (size, size), interpolation=interpolation)

        return resized


img = cv2.imread(image_path)
resize_img = self.crop_square(img, 300)
## perform your calculation on the resized_img and continue with the original img then 
colorness =  self.image_colorfulness(resize_img)

僅調整大小

如果您不想裁剪而只調整圖像大小,可以通過查看square_crop函數中的這行代碼來實現。

resized = cv2.resize(crop_img, (size, size), interpolation=interpolation)

測試結果

  • 我測試了一個5.0 MB *.PNG圖像,然后在cv2.split中使用標准圖像輸入,它在8 Minutes中處理。

在圖像調整大小之后,調整大小的圖像上的時間減少到0.001 ms

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM