241 lines
7.4 KiB
Python
241 lines
7.4 KiB
Python
import cv2
|
|
import numpy as np
|
|
|
|
locations = np.empty((0,2), dtype=np.int32)
|
|
|
|
def click_event(event, x, y, flags, params):
|
|
global locations
|
|
if event == cv2.EVENT_LBUTTONDOWN:
|
|
print(img[y][x])
|
|
locations = np.append(locations, [[y,x]] , axis=0)
|
|
|
|
def selectPointsM(img):
|
|
global locations
|
|
|
|
cv2.namedWindow('Select color')
|
|
cv2.setMouseCallback('Select color', click_event)
|
|
|
|
while True:
|
|
cv2.imshow('Select color', img)
|
|
if cv2.waitKey(1) & 0xFF == 27:
|
|
break
|
|
|
|
cv2.destroyAllWindows()
|
|
return locations
|
|
|
|
def MeanShift(src, window, criteria):
|
|
|
|
for _ in range(criteria[1]):
|
|
ret, window = Iteration(src, window, criteria[2])
|
|
if ret:
|
|
return (True, window)
|
|
|
|
return (False, window)
|
|
|
|
def Iteration(src, window, criteria):
|
|
if window[0] < 0:
|
|
window = (0, window[1], window[2], window[3])
|
|
if window[1] < 0:
|
|
window = (window[0], 0, window[2], window[3])
|
|
|
|
roi = src[window[1]:window[1]+window[3], window[0]:window[0]+window[2]]
|
|
|
|
#iteracija 1
|
|
# x = 0
|
|
# y = 0
|
|
# num = 0
|
|
# for i in range(roi.shape[0]):
|
|
# for j in range(roi.shape[1]):
|
|
# if roi[i][j] > 0:
|
|
# x += j
|
|
# y += i
|
|
# num += 1
|
|
|
|
#iteracija 2
|
|
# nonzero_indices = np.nonzero(roi)
|
|
# nonzero_values = roi[nonzero_indices]
|
|
|
|
# x = np.sum(nonzero_indices[1])
|
|
# y = np.sum(nonzero_indices[0])
|
|
# num = np.count_nonzero(nonzero_values)
|
|
|
|
#iteracija 3
|
|
mom = cv2.moments(roi)
|
|
x = 0
|
|
y = 0
|
|
if mom['m00'] != 0:
|
|
x = int(mom['m10'] / mom['m00'])
|
|
y = int(mom['m01'] / mom['m00'])
|
|
x = int(x - window[2] / 2)
|
|
y = int(y - window[3] / 2)
|
|
window = (window[0] + x, window[1] + y, window[2], window[3])
|
|
|
|
if x < criteria and y < criteria:
|
|
return (True, window)
|
|
|
|
return (False, window)
|
|
|
|
def CamShift(src, window, criteria):
|
|
ret = False
|
|
for _ in range(criteria[1]):
|
|
ret, window = Iteration(src, window, criteria[2])
|
|
window = changeSize(src, window)
|
|
|
|
|
|
return (ret, window)
|
|
|
|
def changeSize(src, window):
|
|
roi = src[window[1]:window[1]+window[3], window[0]:window[0]+window[2]]
|
|
mom = cv2.moments(roi)
|
|
|
|
ratio = window[2] / window[3]
|
|
if mom['m00'] != 0:
|
|
w = 2 * np.sqrt(mom['m00'] / 256)
|
|
h = w / ratio
|
|
window = (window[0], window[1], int(w), int(h))
|
|
|
|
if window[0] < 0:
|
|
window = (0, window[1], window[2], window[3])
|
|
if window[1] < 0:
|
|
window = (window[0], 0, window[2], window[3])
|
|
if window[0] + window[2] > src.shape[1]:
|
|
window = (src.shape[1] - window[2], window[1], window[2], window[3])
|
|
if window[1] + window[3] > src.shape[0]:
|
|
window = (window[0], src.shape[0] - window[3], window[2], window[3])
|
|
if window[2] < 10:
|
|
window = (window[0], window[1], 10, window[3])
|
|
if window[3] < 10:
|
|
window = (window[0], window[1], window[2], 10)
|
|
|
|
return window
|
|
|
|
def selectObjectH(frame, target_hist):
|
|
|
|
target_hist = target_hist.astype(np.float32)
|
|
cv2.normalize(target_hist, target_hist, 0, 1, cv2.NORM_MINMAX)
|
|
|
|
hsvImg = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
|
|
h_channel = hsvImg[:, :, 0]
|
|
#s_channel = hsvImg[:, :, 1]
|
|
|
|
#probabilityImg = np.zeros(shape=(hsvImg.shape[0], hsvImg.shape[1], 1) , dtype=np.float32)
|
|
|
|
# Stack the H and S channels
|
|
# hs_img = np.stack((h_channel, s_channel), axis=-1)
|
|
|
|
# for i in range(hs_img.shape[0]):
|
|
# for j in range(hs_img.shape[1]):
|
|
# probabilityImg[i][j] = target_hist[int(h_channel[i][j])]
|
|
# satProp = target_hist[int(hs_img[i][j][1])]
|
|
# probabilityImg[i][j] = hueProp * satProp
|
|
|
|
probabilityImg = target_hist[h_channel.astype(np.uint8)]
|
|
|
|
|
|
cv2.normalize(probabilityImg, probabilityImg, 0, 255, cv2.NORM_MINMAX)
|
|
probabilityImg = probabilityImg.astype(np.uint8)
|
|
|
|
mask = cv2.inRange(probabilityImg, 100, 255)
|
|
|
|
contour, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
|
|
|
maxContour = max(contour, key=cv2.contourArea)
|
|
x, y, w, h = cv2.boundingRect(maxContour)
|
|
return (x, y, w, h)
|
|
|
|
def selectObjectHS(frame, target_hist):
|
|
|
|
target_hist = target_hist.astype(np.float32)
|
|
cv2.normalize(target_hist, target_hist, 0, 1, cv2.NORM_MINMAX)
|
|
hsvImg = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
|
|
|
|
# probabilityImg = np.zeros(shape=(hsvImg.shape[0], hsvImg.shape[1], 1) , dtype=np.float32)
|
|
# for i in range(hsvImg.shape[0]):
|
|
# for j in range(hsvImg.shape[1]):
|
|
# hueProp = target_hist[int(hsvImg[i][j][0])][0]
|
|
# satProp = target_hist[int(hsvImg[i][j][1])][1]
|
|
# probabilityImg[i][j] = hueProp * satProp
|
|
|
|
|
|
hue_values = hsvImg[..., 0].astype(np.uint8)
|
|
sat_values = hsvImg[..., 1].astype(np.uint8)
|
|
hue_props = target_hist[hue_values.flatten(), 0].reshape(hsvImg.shape[:2])
|
|
sat_props = target_hist[sat_values.flatten(), 1].reshape(hsvImg.shape[:2])
|
|
probabilityImg = (hue_props * sat_props).astype(np.float32)
|
|
|
|
|
|
cv2.normalize(probabilityImg, probabilityImg, 0, 255, cv2.NORM_MINMAX)
|
|
probabilityImg = probabilityImg.astype(np.uint8)
|
|
|
|
mask = cv2.inRange(probabilityImg, 100, 255)
|
|
|
|
contour, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
|
|
|
|
maxContour = max(contour, key=cv2.contourArea)
|
|
x, y, w, h = cv2.boundingRect(maxContour)
|
|
return (x, y, w, h)
|
|
|
|
def selectObject(frame, target_hist):
|
|
|
|
if target_hist.shape[0] == 180:
|
|
return selectObjectH(frame, target_hist)
|
|
else:
|
|
return selectObjectHS(frame, target_hist)
|
|
|
|
def calcHistH(roi):
|
|
histogram = np.zeros(180, dtype=int)
|
|
for i in range(roi.shape[0]):
|
|
for j in range(roi.shape[1]):
|
|
histogram[roi[i][j][0]] += 1
|
|
|
|
return histogram
|
|
|
|
def calcHistHS(roi):
|
|
histogramH = np.zeros(256, dtype=int)
|
|
histogramS = np.zeros(256, dtype=int)
|
|
for i in range(roi.shape[0]):
|
|
for j in range(roi.shape[1]):
|
|
histogramH[roi[i][j][0]] += 1
|
|
histogramS[roi[i][j][1]] += 1
|
|
|
|
histogram = np.stack(arrays=(histogramH, histogramS), axis=-1)
|
|
return histogram
|
|
|
|
def calcHist(roi, numOfchannels=1):
|
|
if numOfchannels == 1:
|
|
return calcHistH(roi)
|
|
else:
|
|
return calcHistHS(roi)
|
|
|
|
def calcBackProjectH(frame, target_hist):
|
|
target_hist = target_hist.astype(np.float32)
|
|
cv2.normalize(target_hist, target_hist, 0, 1, cv2.NORM_MINMAX)
|
|
|
|
hsvImg = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
|
|
h_channel = hsvImg[:, :, 0]
|
|
probabilityImg = target_hist[h_channel.astype(np.uint8)]
|
|
cv2.normalize(probabilityImg, probabilityImg, 0, 255, cv2.NORM_MINMAX)
|
|
return probabilityImg.astype(np.uint8)
|
|
|
|
def calcBackProjectHS(frame, target_hist):
|
|
target_hist = target_hist.astype(np.float32)
|
|
cv2.normalize(target_hist, target_hist, 0, 1, cv2.NORM_MINMAX)
|
|
hsvImg = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
|
|
|
|
hue_values = hsvImg[..., 0].astype(np.uint8)
|
|
sat_values = hsvImg[..., 1].astype(np.uint8)
|
|
hue_props = target_hist[hue_values.flatten(), 0].reshape(hsvImg.shape[:2])
|
|
sat_props = target_hist[sat_values.flatten(), 1].reshape(hsvImg.shape[:2])
|
|
probabilityImg = (hue_props * sat_props).astype(np.float32)
|
|
|
|
|
|
cv2.normalize(probabilityImg, probabilityImg, 0, 255, cv2.NORM_MINMAX)
|
|
return probabilityImg.astype(np.uint8)
|
|
|
|
def calcBackProject(frame, target_hist):
|
|
if target_hist.shape[0] == 180:
|
|
return calcBackProjectH(frame, target_hist)
|
|
else:
|
|
return calcBackProjectHS(frame, target_hist)
|
|
|