I'm new to computer vision and numpy.
I wrote a simple script to seperate red, green and blue colors from the original image by using the kNN algorithm. After reading through some numpy tutorials, I'm under the impression that the performance of my script can be improved heavily. So here are my questions:
- Is there a way to avoid the call to np_pixel = np.asarray(...) for each of the pixels? I can't find a format for the trainData that would allow me that.
- Is there a way to feed the whole image into the findNearest method? This would make it possible to avoid the slow python loop.
- Do you see any other ways to improve the performance or length of this script?
import cv2
import numpy as np
trainData = np.array([[255, 0, 0], [0, 255, 0], [0, 0, 255]], dtype=np.float32)
# Labels each one of the BGR channels as numbers 0, 1, 2 respectively
responses = np.array([[0], [1], [2]], dtype=np.float32)
imgPath = "../Images/RGB.png"
img = cv2.imread(imgPath)
if img is None:
raise FileNotFoundError("'{0}' could not be opened!".format(imgPath))
knn = cv2.ml.KNearest_create()
knn.train(trainData, cv2.ml.ROW_SAMPLE, responses)
height, width, depth = img.shape
colorLayers = dict()
colorLayers[0] = np.zeros((height, width, 3), dtype=np.float32)
colorLayers[1] = np.zeros((height, width, 3), dtype=np.float32)
colorLayers[2] = np.zeros((height, width, 3), dtype=np.float32)
for row in range(height):
for col in range(width):
np_pixel = np.asarray([img[row, col]], dtype=np.float32)
ret, results, neighbours, dist = knn.findNearest(np_pixel, 1)
int_result = int(results)
if int_result == 0:
color = np.asarray([255, 0, 0]).astype(np.float32)
elif int_result == 1:
color = np.asarray([0, 255, 0]).astype(np.float32)
else:
color = np.asarray([0, 0, 255]).astype(np.float32)
colorLayers[int_result][row, col] = color
cv2.imshow('Original', img)
cv2.imshow('Blue', colorLayers[0])
cv2.imshow('Green', colorLayers[1])
cv2.imshow('Red', colorLayers[2])
cv2.waitKey(0)