簡體   English   中英

使用 Python 對圖像中高於閾值的像素值求和的最快方法

[英]Fastest way to sum the values of the pixels above a threshold in an image with Python

我試圖找到最好的方法來檢索大於某個閾值的像素的總和。 例如,如果我的閾值是 253,我得到 10 個像素是 254,另外 10 個像素是 255,我希望得到10*254 + 10*255 = 5090 - 超過像素的總強度臨界點。

我找到了一種方法來使用np.histogram

import cv2, time
import numpy as np
threshold = 1
deltaImg = cv2.imread('image.jpg')
t0=time.time()
histogram = np.histogram(deltaImg,256-threshold,[threshold,256])
histoSum = sum(histogram[0]*histogram[1][:-1])
print(histoSum)
print("time = %.2f ms" % ((time.time()-t0)*1000))

這個作品和我得到的像素衣被合計是比選擇的閾值更大的總和。 但是,我不確定這是最好/最快的方法。 顯然,閾值越大,動作就越快。

有沒有人知道如何使用更快的算法獲得正確的結果?

干得好:

import numpy as np
image = np.random.randint(0,256,(10,10))
threshold = 1
res = np.sum(image[image > threshold])

這個操作:

%%timeit
res = np.sum(image[image >=threshold])

5.43 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)需要5.43 µs ± 137 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

雖然 OP 的方法從根本上是不准確的,但其基本思想仍然可以用來制作一種對整數數組(例如灰度圖像)有效的方法:

def sum_gt_hist(arr, threshold):
    values = np.arange(threshold, np.max(arr) + 1)
    hist, edges = np.histogram(arr, values + 0.5)
    return sum(values[1:] * hist)

然而,這並不理想,因為它比應有的更復雜( np.histogram()是一個相對復雜的函數,它計算的中間信息比需要的要多得多)並且僅適用於整數值。

@sehan2 的回答中提出了一種更簡單且仍然純粹的 NumPy 方法:

import numpy as np


def sum_gt_np(arr, threshold):
    return np.sum(arr[arr > threshold])

雖然以上將是首選的 NumPy-only 解決方案,但使用基於 Numba 的簡單解決方案可以獲得更快的執行(和內存效率):

import numba as nb


@nb.njit
def sum_gt_nb(arr, threshold):
    arr = arr.ravel()
    result = 0
    for x in arr:
        if x > threshold:
            result += x
    return result

使用代表圖像的隨機 100x100 數組對上述內容進行基准測試,將得到:

import numpy as np


np.random.seed(0)
arr = np.random.randint(0, 256, (100, 100))  # generate a random image
threshold = 253  # set a threshold

funcs = sum_gt_hist, sum_gt_np, sum_gt_nb
for func in funcs:
    print(f"{func.__name__:16s}", end='  ')
    print(func(arr, threshold), end='  ')
    %timeit func(arr, threshold)

# sum_gt_hist       22397  355 µs ± 8.67 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
# sum_gt_np         22397  10.1 µs ± 438 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# sum_gt_nb         22397  1.19 µs ± 33.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

這表明sum_gt_nb()sum_gt_np()快得多,而sum_gt_hist()又比sum_gt_hist()快得多。

我不知道這是否是最快的,但它很簡單。 在 Python/OpenCV 中,僅將低於閾值的像素設為零,保持高於閾值的值作為原始值。 然后簡單地計算不為零的值。

我創建了一個簡單的斜坡圖像,寬度為 100 像素,從頂部的 255 到底部的 0,以 1 灰度級為增量。

輸入:

在此處輸入圖片說明

import cv2
import numpy as np

# read image
img = cv2.imread('ramp.png')
print(img.shape)

# convert img to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold to zero below threshold, but keep values above threshold
# note: to count all values of 254 and 255, use threshold at 253
thresh = cv2.threshold(gray, 253, 255, cv2.THRESH_TOZERO)[1]

# sum non-zero pixel values
sum = np.sum(thresh[np.where(thresh != 0)])
print("actual count:", sum)

# compute the expected count
sum2 = 100*254+100*255
print("computed count:", sum2)

# show results
cv2.imshow('thresh', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果:
 actual count: 50900 computed count: 50900

暫無
暫無

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

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