Поскольку вы уже используете OpenCV , вы также можете использовать его оптимизированный код SIMD для выполнения установки порога.Он не только короче и проще в обслуживании, но и намного быстрее.Это выглядит так:
_, thres = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
Да, все!Это заменяет весь ваш код.
Тестирование и демонстрация
Заимствуя из других ответов, я собрал:
- aметод с использованием двойных
for
циклов, - метода Numpy и
- метода OpenCV, который я предлагаю
, и запуск некоторых тестов синхронизации внутри IPython.Итак, я сохранил этот код как thresh.py
#!/usr/bin/env python3
import cv2
import numpy as np
def method1(img):
"""Double loop over pixels"""
h = img.shape[0]
w = img.shape[1]
img_thres= np.zeros((h,w))
# loop over the image, pixel by pixel
for y in range(0, h):
for x in range(0, w):
# threshold the pixel
pixel = img[y, x]
img_thres[y, x] = 0 if pixel < 128 else pixel
return img_thres
def method2(img):
"""Numpy indexing"""
img_thres = img
img_thres[ img < 128 ] = 0
return img_thres
def method3(img):
"""OpenCV thresholding"""
_, thres = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
return thres
img = cv2.imread("gradient.png",cv2.IMREAD_GRAYSCALE)
Затем я запустил IPython и сделал:
%load thresh.py
Затем я рассчитал три метода:
%timeit method1(img)
81 ms ± 545 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit method2(img)
24.5 µs ± 818 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit method3(img)
3.03 µs ± 79.5 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Обратите внимание, что первый результат в миллисекундах, тогда как два других в микросекундах.Версия Numpy в 3300 раз быстрее, чем циклы for, и что версия OpenCV в 27000 раз быстрее !!!
Вы можете проверить, что они дают одинаковый результат, суммируя различия в изображениях, как показано ниже:
np.sum(method1(img)-method3(img))
0.0
Начальное изображение:
Изображение результата: