numpy / линейная алгебра - быстрая 16-битная гистограмма - PullRequest
1 голос
/ 29 января 2020

Если у меня есть изображение, сделанное из uint16s, и я хочу вычислить гистограмму для каждого бита, то есть вектор 'x' из 0..65535, который содержит значение интенсивности, и вектор y, который является числом выборок, которые есть это значение, есть ли векторизованный numpy / линейный способ вычислить это?

Ответы [ 2 ]

1 голос
/ 29 января 2020

Я сделал это очевидным образом с Numpy, и, используя размеры вашего изображения на моей маме c, это займет 300 мс. Затем я проделал то же самое с OpenCV, и он в 33 раза быстрее при 9 мс!

#!/usr/bin/env python3

import cv2
import numpy as np

# Dimensions - height, width
h, w = 2160, 2560

# Known image, channel0=1, channel1=3, channel2=5, channel3=65535
R =  np.zeros((h,w,4), dtype=np.uint16)
R[...,0] = 1
R[...,1] = 3
R[...,2] = 5
R[...,3] = 65535

def npHistogram(R):
    """Generate histogram using Numpy"""
    H, _ = np.histogram(R,65536)
    return H

def OpenCVHistogram(R):
    """Generate histogram using OpenCV"""
    H = cv2.calcHist([R.ravel()], [0], None, [65536], [0,65536]) 
    return H

A = npHistogram(R)
B = OpenCVHistogram(R)

#%timeit npHistogram(R)
#%timeit OpenCVHistogram(R)

Результаты

Используя I Python, я получил эти значения времени

%timeit npHistogram(R)
300 ms ± 11.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit OpenCVHistogram(R)
9.02 ms ± 226 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Ключевые слова : Python, гистограмма, медленно, Numpy, гистограмма np, ускорение, OpenCV, обработка изображений.

0 голосов
/ 05 февраля 2020

Хорошо, если OpenCV слишком большая зависимость для вас, чтобы получить время обработки 9 мс вместо 300 мс, как насчет Numba ? Это выполняется за 10 мс.

#!/usr/bin/env python3

import numpy as np
from numba import jit

# Dimensions - height, width
h, w = 2160, 2560

# Known image, channel0=1, channel1=3, channel2=5, channel3=65535
R =  np.zeros((h,w,4), dtype=np.uint16)
R[...,0] = 1
R[...,1] = 3
R[...,2] = 5
R[...,3] = 65535

@jit(nopython=True, nogil=True)
def NumbaHistogram(pixels):
    """Histogram of uint16 image"""
    H = np.zeros(65536, dtype=np.int32)
    for i in range(len(pixels)):
        H[pixels[i]] += 1
    return H

#%timeit q = NumbaHistogram(R.ravel()) 

Результаты

%timeit NumbaHistogram(R.ravel())                                                                                                                  
10.4 ms ± 54.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...