I want to generate the output that is a threshold. And my error:
img_thres = n_pix[y, x]
TypeError: 'int' object is not subscriptable
import cv2
import numpy as np
import matplotlib as plt
img = cv2.imread("cicek.png",0)
img_rgb = cv2.imread("cicek.png")
h = img.shape[0]
w = img.shape[1]
img_thres= []
n_pix = 0
# 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]
if pixel < 0.5:
n_pix = 0
img_thres = n_pix[y, x]
cv2.imshow("cicek", img_thres)
As you are already using OpenCV, you may as well use its optimised SIMD code to do your thresholding. Not only is it shorter and easier to maintain, it is also miles faster. It looks like this:
_, thres = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
Yes, that's it! That replaces all your code.
Benchmarking and demo
Borrowing heavily from other answers, I put together:
for
loops,and ran some timing tests inside IPython. So, I saved this code as 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)
Then, I started IPython and did:
%load thresh.py
Then, I timed the three methods:
%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)
Note that the first result is in milliseconds whereas the other two are in microseconds. The Numpy version is 3,300 times faster than the for loops, and that the OpenCV version is 27,000 times faster!!!
You can check they produce the same result by totting up the differences in the images like this:
np.sum(method1(img)-method3(img))
0.0
Start image:
Result image: