Specific bounding box color - python-3.x

Can someone help me to modify this existing code to use different color for the bounding box i want to detect?
For example: If a person detect bounding box will be red and if animals or pets detect will be green and other object would be blue, been exploring for a week still no luck for modifying it if anyone can explain or help would be much appreciated. Thanks!
import os
import argparse
import cv2
import numpy as np
import sys
import glob
import importlib.util
parser = argparse.ArgumentParser()
parser.add_argument('--modeldir', help='Folder the .tflite file is located in', required=True)
parser.add_argument('--graph', help='Name of the .tflite file, if different than detect.tflite', default='detect.tflite')
parser.add_argument('--labels', help='Name of the labelmap file, if different than labelmap.txt', default='labelmap.txt')
parser.add_argument('--threshold', help='Minimum confidence threshold for displaying detected objects', default=0.5)
parser.add_argument('--image', help='Name of the single image to perform detection on. To run detection on multiple images, use --imagedir', default=None)
parser.add_argument('--imagedir', help='Name of the folder containing images to perform detection on. Folder must contain only images.', default=None)
parser.add_argument('--edgetpu', help='Use Coral Edge TPU Accelerator to speed up detection', action='store_true')
args = parser.parse_args()
MODEL_NAME = args.modeldir
GRAPH_NAME = args.graph
LABELMAP_NAME = args.labels
min_conf_threshold = float(args.threshold)
use_TPU = args.edgetpu
IM_NAME = args.image
IM_DIR = args.imagedir
if (IM_NAME and IM_DIR):
print('Error! Please only use the --image argument or the --imagedir argument, not both. Issue "python TFLite_detection_image.py -h" for help.')
sys.exit()
if (not IM_NAME and not IM_DIR):
IM_NAME = 'test1.jpg'
pkg = importlib.util.find_spec('tflite_runtime')
if pkg:
from tflite_runtime.interpreter import Interpreter
if use_TPU:
from tflite_runtime.interpreter import load_delegate
else:
from tensorflow.lite.python.interpreter import Interpreter
if use_TPU:
from tensorflow.lite.python.interpreter import load_delegate
if use_TPU:
if (GRAPH_NAME == 'detect.tflite'):
GRAPH_NAME = 'edgetpu.tflite'
CWD_PATH = os.getcwd()
if IM_DIR:
PATH_TO_IMAGES = os.path.join(CWD_PATH,IM_DIR)
images = glob.glob(PATH_TO_IMAGES + '/*')
elif IM_NAME:
PATH_TO_IMAGES = os.path.join(CWD_PATH,IM_NAME)
images = glob.glob(PATH_TO_IMAGES)
PATH_TO_CKPT = os.path.join(CWD_PATH,MODEL_NAME,GRAPH_NAME)
PATH_TO_LABELS = os.path.join(CWD_PATH,MODEL_NAME,LABELMAP_NAME)
with open(PATH_TO_LABELS, 'r') as f:
labels = [line.strip() for line in f.readlines()]
if labels[0] == '???':
del(labels[0])
if use_TPU:
interpreter = Interpreter(model_path=PATH_TO_CKPT, experimental_delegates=[load_delegate('libedgetpu.so.1.0')])
print(PATH_TO_CKPT)
else:
interpreter = Interpreter(model_path=PATH_TO_CKPT)
interpreter.allocate_tensors()
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
height = input_details[0]['shape'][1]
width = input_details[0]['shape'][2]
floating_model = (input_details[0]['dtype'] == np.float32)
input_mean = 127.5
input_std = 127.5
for image_path in images:
image = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
imH, imW, _ = image.shape
image_resized = cv2.resize(image_rgb, (width, height))
input_data = np.expand_dims(image_resized, axis=0)
if floating_model:
input_data = (np.float32(input_data) - input_mean) / input_std
interpreter.set_tensor(input_details[0]['index'],input_data)
interpreter.invoke()
boxes = interpreter.get_tensor(output_details[0]['index'])[0] # Bounding box coordinates of detected objects
classes = interpreter.get_tensor(output_details[1]['index'])[0] # Class index of detected objects
scores = interpreter.get_tensor(output_details[2]['index'])[0] # Confidence of detected objects
for i in range(len(scores)):
if ((scores[i] > min_conf_threshold) and (scores[i] <= 1.0)):
ymin = int(max(1,(boxes[i][0] * imH)))
xmin = int(max(1,(boxes[i][1] * imW)))
ymax = int(min(imH,(boxes[i][2] * imH)))
xmax = int(min(imW,(boxes[i][3] * imW)))
cv2.rectangle(image, (xmin,ymin), (xmax,ymax), (10, 255, 0), 2)
object_name = labels[int(classes[i])] # Look up object name from "labels" array using class index
label = '%s: %d%%' % (object_name, int(scores[i]*100)) # Example: 'person: 72%'
labelSize, baseLine = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.7, 2) # Get font size
label_ymin = max(ymin, labelSize[1] + 10) # Make sure not to draw label too close to top of window
cv2.rectangle(image, (xmin, label_ymin-labelSize[1]-10), (xmin+labelSize[0], label_ymin+baseLine-10), (255, 255, 255), cv2.FILLED) # Draw white box to put label text in
cv2.putText(image, label, (xmin, label_ymin-7), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 0), 2)
cv2.imshow('Object detector', image)
if cv2.waitKey(0) == ord('q'):
break
cv2.destroyAllWindows()

Basically what you want to do is make a dict where the key is the class and the value is a color in the same format that is here.
cv2.rectangle(image, (xmin,ymin), (xmax,ymax), (10, 255, 0), 2)
Replace (10, 255, 0) with something like color_dict[classes[i]] and then you will be able to get a different color for each class.

Related

Opencv detect side column and text

I am working on a opencv project, where I need to detect names column and any black color border present around the ROI. I am quite new with image processing so unable to figure out how to do this.
This is one of the sample images from which I wish to remove the column on the right (one containing all the details). But not all images contain this column, so I wish to detect the column and remove it from the image.
Here is the expected output.
EDIT
Here is the code that I have tried (I have tried using detection of largest rectangles in the region):
import cv2
from cv2 import dilate
from cv2 import findContours
import imutils
import numpy as np
image_name = 'test2.jpg'
og_plan = cv2.imread('test_images/{}'.format(image_name))
res = og_plan.copy()
img_height, img_width, img_channel = og_plan.shape
img_area = img_width * img_height
if og_plan.shape[0] > 800:
res = imutils.resize(res, height=720)
img_height, img_width, img_channel = res.shape
img_area = img_width * img_height
print(res.shape)
print(img_area)
hsv_plan = cv2.cvtColor(res, cv2.COLOR_BGR2HSV)
grey_plan = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
blue_min = np.array([14,100,76])
blue_max = np.array([130,255,255])
bluemask = cv2.inRange(hsv_plan,blue_min,blue_max)
blue_output = cv2.bitwise_and(hsv_plan, hsv_plan, mask=bluemask)
grey_mask = cv2.cvtColor(blue_output, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(grey_mask, 100, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
ret2, thresh2 = cv2.threshold(grey_plan, 160, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
kernel = np.ones((3,3), np.uint8)
dil = dilate(thresh, kernel, iterations=2)
dil_grey = dilate(thresh2, kernel, iterations=2)
cont,hier = findContours(dil, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cont1,hier1 = findContours(dil_grey, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
def max_rect(cntrs):
ar = {}
for cnt in cntrs:
x,y,w,h = cv2.boundingRect(cnt)
area = w*h
ar[area] = (x,y,w,h)
# ar = sorted(ar, key=ar.keys, reverse=True)
return ar
area_dict = max_rect(cont1)
roi_area = []
for area in area_dict:
if area >= img_area*0.1 and area < img_area:
print(area)
roi_area.append(area)
plan_no = 1
for a in roi_area:
plan = area_dict[a]
# del area_dict[a]
x,y,w,h = plan
roi = res[y:y+h, x:x+w]
print(plan)
cv2.rectangle(res, (x-5,y-5), (x+w+5, y+h+5), (255,255,0), 2)
cv2.imshow('ROI-{}'.format(image_name),roi)
cv2.imwrite('./result/{}_plan-{}.png'.format(image_name,plan_no),roi)
cv2.waitKey(0)
plan_no += 1
'''plan1 = area_dict[max(area_dict)]
del area_dict[max(area_dict)]
plan2 = area_dict[max(area_dict)]
x,y,w,h = plan1
x1,y1,w1,h1 = plan2
roi1 = res[y:y+h, x:x+w]
roi2 = res[y1:y1+h1, x1:x1+w1]
print(plan1, plan2)
cv2.rectangle(res, (x-5,y-5), (x+w+5, y+h+5), (255,255,0), 2)
cv2.rectangle(res, (x1-5,y1-5), (x1+w1+5, y1+h1+20), (255,255,0), 2)'''

My code is running continuously in jupyter notebook and asterisk sign is remain on cell of jupyter notebook

import numpy as np
import cv2
import keras
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf
model = tf.keras.models.load_model(r"C:\Users\ASUS\best_model_dataflair3.h5")
background = None
accumulated_weight = 0.5
ROI_top = 100
ROI_bottom = 300
ROI_right = 150
ROI_left = 350
def cal_accum_avg(frame, accumulated_weight):
global background
if background is None:
background = frame.copy().astype("float")
return None
cv2.accumulateWeighted(frame, background, accumulated_weight)
def segment_hand(frame, threshold=25):
global background
diff = cv2.absdiff(background.astype("uint8"), frame)
_ , thresholded = cv2.threshold(diff, threshold, 255, cv2.THRESH_BINARY)
#Fetching contours in the frame (These contours can be of hand or any other object in foreground) ...
image, contours, hierarchy = cv2.findContours(thresholded.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# If length of contours list = 0, means we didn't get any contours...
if len(contours) == 0:
return None
else:
# The largest external contour should be the hand
hand_segment_max_cont = max(contours, key=cv2.contourArea)
# Returning the hand segment(max contour) and the thresholded image of hand...
return (thresholded, hand_segment_max_cont)
cam = cv2.VideoCapture(0)
num_frames = 0
while True:
ret,frame = cam.read()
# filpping the frame to prevent inverted image of captured frame...
frame = cv2.flip(frame, 1)
frame_copy = frame.copy()
# ROI from the frame
roi = frame[ROI_top:ROI_bottom, ROI_right:ROI_left]
gray_frame = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
gray_frame = cv2.GaussianBlur(gray_frame, (9, 9), 0)
if num_frames < 70:
cal_accum_avg(gray_frame, accumulated_weight)
cv2.putText(frame_copy, "FETCHING BACKGROUND...PLEASE WAIT", (80, 400), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,0,255), 2)
else:
# segmenting the hand region
hand = segment_hand(gray_frame)
# Checking if we are able to detect the hand...
if hand is not None:
thresholded, hand_segment = hand
# Drawing contours around hand segment
cv2.drawContours(frame_copy, [hand_segment + (ROI_right, ROI_top)], -1, (255, 0, 0),1)
cv2.imshow("Thesholded Hand Image", thresholded)
thresholded = cv2.resize(thresholded, (64, 64))
thresholded = cv2.cvtColor(thresholded, cv2.COLOR_GRAY2RGB)
thresholded = np.reshape(thresholded, (1,thresholded.shape[0],thresholded.shape[1],3))
pred = model.predict(thresholded)
cv2.putText(frame_copy, word_dict[np.argmax(pred)], (170, 45), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
# Draw ROI on frame_copy
cv2.rectangle(frame_copy, (ROI_left, ROI_top), (ROI_right, ROI_bottom), (255,128,0), 3)
# incrementing the number of frames for tracking
num_frames += 1
# Display the frame with segmented hand
cv2.putText(frame_copy, "DataFlair hand sign recognition_ _ _", (10, 20), cv2.FONT_ITALIC, 0.5, (51,255,51), 1)
cv2.imshow("Sign Detection", frame_copy)
# Close windows with Esc
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cam.release()
cv2.destroyAllWindows()
This is the code for predicting the hand gesture but camera is not opening. The code is running continuously but not showing any error.
Please anyone reslove this issue. This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN)to use the following CPU instructions in performance-critical operations:
I am getting this in anaconda prompt

Comparing maxVal's from OpenCV matchTemplate for dynamic template matching

I am trying to do some dynamic template matching with cv2.matchTemplate. The template is:
and the image I am matching it to is:
I am adjusting the size and angle of the template and then grabbing maxVal and maxLoc from cv2.matchTemplate and storing them in a dict with maxVal as the keys. I'm then grabbing max(data.keys()) as the "best" match from result = cv2.matchTemplate(image, resized_template, cv2.TM_CCORR_NORMED). When I loop through all of the keys and plot them on the image, there are some that find the mickey head much better than max(data.keys()).
This is the region for "best" match:
#Find best match from scores
best_match = max(scores.keys())
#Output image
image_copy = color_image.copy()
#Create rectangle around best match
cv2.rectangle(image_copy, (data[best_match][1][0], data[best_match][1][1]), (data[best_match][1][0] + data[best_match][0][0], data[best_match][1][1] + data[best_match][0][1]), (255, 255, 255), 2)
plt.imshow(image_copy)
But this region appears to locate it much more accurately:
image_copy = color_image.copy()
for n in list(data.keys())[69:70:1]:
#Create rectangle around best match
cv2.rectangle(image_copy, (data[n][1][0], data[n][1][1]), (data[n][1][0] + data[n][0][0], data[n][1][1] + data[n][0][1]), (255, 255, 255), 2)
cv2.imwrite('output_1.jpg', image_copy)
plt.imshow(image_copy)
Am I miss interpreting what the maxVal from cv2.matchTemplate actually represents? If so, how can I select the actual "best" region based on some value or criteria? Here's the full code:
#Import packages
import numpy as np
import matplotlib.pyplot as plt
import cv2
import imutils
import os
#Import template
template = cv2.imread(templates_dir + '\\' + os.listdir(templates_dir)[3])
gray_template = cv2.cvtColor(template, cv2.COLOR_RGB2GRAY)
#Import image
image = cv2.imread(images_dir + '\\' + os.listdir(images_dir)[5])
color_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
#Image dims
image_h = image.shape[1]
image_w = image.shape[0]
#Processing loop scaling the template
#Scores dict
scores = {}
#Data dict of structure (maxVal: (template dims, locs, angle))
data = {}
#Edge images
template = cv2.Canny(gray_template, 80, 200)
image = cv2.Canny(gray_image, 80, 200)
#Loop through different template scales
for scale in np.linspace(0.2, 1.5, 15):
#Loop through different template rotations
for angle in np.linspace(0, 360, 25)[:-1]:
#Rotate template
template_rotated = imutils.rotate(template, angle)
#Resize template
resized_template = imutils.resize(template_rotated, width = int(template_rotated.shape[0] * scale))
#Dims of resized template
template_h = resized_template.shape[1]
template_w = resized_template.shape[0]
#Break from loop if the template becomes bigger than the image
if template_h > image_h or template_w > image_w:
break
#Run template through image
result = cv2.matchTemplate(image, resized_template, cv2.TM_CCORR_NORMED)
#Get matching score and location
(_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)
#Add correlation value and result to scores
scores[str(maxVal)] = result
#Add info to data
data[str(maxVal)] = ((template_h, template_w), (maxLoc[0], maxLoc[1]), angle)
#Find best match from scores
best_match = max(scores.keys())
#Output image
image_copy = color_image.copy()
#Create rectangle around best match
cv2.rectangle(image_copy, (data[best_match][1][0], data[best_match][1][1]), (data[best_match][1][0] + data[best_match][0][0], data[best_match][1][1] + data[best_match][0][1]), (0, 0, 255), 2)
plt.imshow(image_copy)

Undefined name problem in camera calibration

I am using the same code that is provided by the OpenCv tutorial, it was working few weeks ago, today I was trying to run it is says that gray name is not defined!! can some one find me the error?
import numpy as np
#import matplotlib.pyplot as plt
import cv2
import glob
import os
def draw(img, corners, imgpts):
corner = tuple(corners[0].ravel())
img = cv2.line(img, corner, tuple(imgpts[0].ravel()), (255,0,0), 5)
img = cv2.line(img, corner, tuple(imgpts[1].ravel()), (0,255,0), 5)
img = cv2.line(img, corner, tuple(imgpts[2].ravel()), (0,0,255), 5)
return img
# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((7*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:7].T.reshape(-1,2)
# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
img_dir = "C:\\Hungary\\Biblography\\Rotating Solitary Wave\\My Work\\Final Work\\Experiment1111 \\Camera Calibration\\Image Processing\\chess"
data_path = os.path.join(img_dir,'*bmp')
images = glob.glob(data_path)
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, (7,7),None)
# If found, add object points, image points (after refining them)
if ret == True:
objpoints.append(objp)
corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
imgpoints.append(corners2)
# Draw and display the corners
img = cv2.drawChessboardCorners(img, (7,7), corners2,ret)
cv2.imshow('img',img)
cv2.waitKey(500)
cv2.destroyAllWindows()
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape [::-1],None,None)
print('Rotation Vector, or the Angles For Each Photo: ', rvecs, '\n')
R = cv2.Rodrigues(rvecs[0])
print('The Rotation Matrix is: ', R)
print('Translation Vector: ', tvecs, '\n')
print(mtx, '\n')
print('Distortion Coefficients ', dist, '\n')
img = cv2.imread('00000274.bmp')
h, w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))
print('Camera Matrix', newcameramtx, '\n')
# undistort
dst = cv2.undistort(img, mtx, dist) #, None, newcameramtx)
p = np.ones_like(dst)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)
# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)
mean_error = 0
for i in range(len(objpoints)):
imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
mean_error += error
print("total error: ", mean_error/len(objpoints))
If you read the opencv document you will find that I did little changes on the code and it was working but today it is raising this error about the gray name is not defined!
Check your path once, and see if images is an empty list. In that case, for loop will not be executed where the gray variable is defined.

OpenCV- Detecting objects excluding shadows

I'm developing a way to detect cars from an aerial view image. I'm using scikit package to calculate the difference of an empty parking lot image and a parking lot with cars to detect the foreign objects. Then I draw the minimum area rectangle around cars.
This works well when there are no shadows.
Empty parking lot image (Please ignore the maroon color car)
Without shadows
With shadows (Problem)
When there are car shadows, they are also in the minimum area rectangle. How can I exclude shadows from the rectangle?
Here is my source
import numpy as np
from skimage.measure import compare_ssim
import imutils
from cv2 import cv2
# construct the argument parse and parse the arguments
# load the two input images
imageA = cv2.imread('empty-lot.png')
imageB = cv2.imread('two-car-lot-shadow.png')
# convert the images to grayscale
grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)
# compute the Structural Similarity Index (SSIM) between the two
# images, ensuring that the difference image is returned
(score, diff) = compare_ssim(grayA, grayB, full=True, gaussian_weights=True, sigma=4)
diff = (diff * 255).astype("uint8")
print("SSIM: {}".format(score))
# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
# loop over the contours
for c in cnts:
# compute the min area rect of the contour and area
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
area = cv2.contourArea(c)
# remove small contour areas
if area < 10000: continue
# convert all coordinates floating point values to int
box = np.int0(box)
# draw a green rectangle
cv2.drawContours(imageB, [box], 0, (0, 255, 0), 2)
# show the output images
cv2.imshow("Modified", imageB)
cv2.imshow("Thresh", thresh)
k = cv2.waitKey() & 0xFF
if k == 27:
exit()
You can convert the image format to HSV, it's easy to remove the shadow.
import ctypes
import numpy as np
import cv2
from pathlib import Path
from typing import List, Union, Callable
def main():
img_bgr: np.ndarray = cv2.imread(str(Path('parking.jpg')))
img_hsv: np.ndarray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(src=img_hsv, lowerb=np.array([0, 64, 153]), upperb=np.array([179, 255, 255]))
img_hsv_modify: np.ndarray = cv2.bitwise_and(img_bgr, img_bgr, mask=mask)
# show_img(img_hsv_modify)
img_mask_gray = cv2.cvtColor(img_hsv_modify, cv2.COLOR_BGR2GRAY)
threshold_val, img_bit = cv2.threshold(img_mask_gray, 0, 255, cv2.THRESH_BINARY) # type: float, np.ndarray
contours, hierarchy = cv2.findContours(img_bit, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
img_bgr_copy = np.copy(img_bgr)
for cnt in filter(lambda c: cv2.contourArea(c) > 10000, contours):
box = cv2.boxPoints(cv2.minAreaRect(cnt))
cv2.drawContours(img_bgr_copy, [np.int0(box)], -1, color=(0, 255, 0), thickness=2)
show_img([img_bgr, img_hsv_modify, cv2.cvtColor(img_bit, cv2.COLOR_GRAY2BGR), img_bgr_copy],
note=['original', 'hsv modify', 'bit', 'result'])
show_img(img_bgr_copy)
if __name__ == '__main__':
main()
And you may ask how do I know the lower bound and upper bound. (Please see the extension code: control_bar_hsv.py)
mask = cv2.inRange(src=img_hsv, lowerb=np.array([0, 64, 153]), upperb=np.array([179, 255, 255]))
result:
all image:
Extension code
show_img:
def show_img(img_list: Union[np.ndarray, List[np.ndarray]], combine_fun: Callable = np.vstack,
window_name='demo', window_size=(ctypes.windll.user32.GetSystemMetrics(0) // 2, ctypes.windll.user32.GetSystemMetrics(1) // 2),
delay_time=0, note: Union[str, List[str]] = None, **options):
if isinstance(img_list, np.ndarray):
img_list = [img_list]
if isinstance(note, str):
print(note)
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
if window_size:
w, h = window_size
cv2.resizeWindow(window_name, w, h)
result_list = []
for idx, img in enumerate(img_list):
img = np.copy(img)
if note and isinstance(note, list) and idx < len(note):
cv2.putText(img, note[idx], org=options.get('org', (50, 50)),
fontFace=options.get('fontFace', cv2.FONT_HERSHEY_SIMPLEX),
fontScale=options.get('fontScale', 2), color=(0, 255, 255), thickness=4)
result_list.append(img)
cv2.imshow(window_name, combine_fun(result_list))
cv2.waitKey(delay_time)
control_bar_hsv.py
It's easy to use, just copy and paste and then tell it where is your image path, done.
and if you want to create other control_bar, maybe ControlBarBase will help you write to write less code.
"""
control_bar_hsv.py
"""
import cv2
from pathlib import Path
import numpy as np
import ctypes
import functools
from typing import Tuple, Callable
class ControlBarBase:
__slots__ = ('img_bgr',)
WAIT_TIME = 500 # milliseconds
CONTROL_PANEL_NAME = 'control_panel'
IMAGE_PANEL_NAME = 'image'
SCREEN_SIZE: Tuple[int, int] = None
def __init__(self, img_path: Path):
self.img_bgr: np.ndarray = cv2.imread(str(img_path))
self.init_window()
self.init_track_bar()
def init_window(self):
for name in (self.CONTROL_PANEL_NAME, self.IMAGE_PANEL_NAME):
cv2.namedWindow(name, cv2.WINDOW_NORMAL)
if self.SCREEN_SIZE:
screen_width, screen_height = self.SCREEN_SIZE
cv2.resizeWindow(name, int(screen_width), int(screen_height))
def init_track_bar(self):
"""
self.build_track_bar(label_name, range_lim=(0, 255), default_value=0, callback)
"""
raise NotImplementedError('subclasses of _ControlBarBase must provide a init_track_bar() method')
def render(self):
raise NotImplementedError('subclasses of _ControlBarBase must provide a render() method.')
def build_track_bar(self, label_name: str,
range_lim: Tuple[int, int], default_value: int, callback: Callable = lambda x: ...):
min_val, max_val = range_lim
cv2.createTrackbar(label_name, self.CONTROL_PANEL_NAME, min_val, max_val, callback)
cv2.setTrackbarPos(label_name, self.CONTROL_PANEL_NAME, default_value)
def get_trackbar_pos(self, widget_name: str):
return cv2.getTrackbarPos(widget_name, self.CONTROL_PANEL_NAME)
def run(self):
while 1:
img, callback_func = self.render()
cv2.imshow(self.IMAGE_PANEL_NAME, img)
if (cv2.waitKey(self.WAIT_TIME) & 0xFF == ord('q') or
cv2.getWindowProperty(self.IMAGE_PANEL_NAME, 0) == -1 or
cv2.getWindowProperty(self.CONTROL_PANEL_NAME, 0) == -1):
callback_func()
break
cv2.destroyAllWindows()
class ControlBarHSV(ControlBarBase):
__slots__ = ()
WAIT_TIME = 500
SCREEN_SIZE = ctypes.windll.user32.GetSystemMetrics(0) / 2, ctypes.windll.user32.GetSystemMetrics(1) / 2
def init_track_bar(self):
self.build_track_bar('HMin', range_lim=(0, 179), default_value=0)
self.build_track_bar('SMin', (0, 255), 0)
self.build_track_bar('VMin', (0, 255), 0)
self.build_track_bar('HMax', (0, 179), 179)
self.build_track_bar('SMax', (0, 255), 255)
self.build_track_bar('VMax', (0, 255), 255)
def render(self):
# get current positions of all trackbars
h_min = self.get_trackbar_pos('HMin')
s_min = self.get_trackbar_pos('SMin')
v_min = self.get_trackbar_pos('VMin')
h_max = self.get_trackbar_pos('HMax')
s_max = self.get_trackbar_pos('SMax')
v_max = self.get_trackbar_pos('VMax')
# Set minimum and max HSV values to display
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
# Create HSV Image and threshold into a range.
hsv = cv2.cvtColor(self.img_bgr, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower, upper)
img_output: np.ndarray = cv2.bitwise_and(self.img_bgr, self.img_bgr, mask=mask)
#functools.wraps(self.render)
def cb_func():
return print(f'cv2.inRange(src=hsv, lowerb=np.array([{h_min}, {s_min}, {v_min}]), upperb=np.array([{h_max}, {s_max}, {v_max}]))')
return img_output, cb_func
if __name__ == '__main__':
from argparse import ArgumentParser
arg_parser = ArgumentParser()
arg_parser.add_argument("src_path", type=Path, help="source image path")
args = arg_parser.parse_args()
obj = ControlBarHSV(args.src_path) # ControlBarHSV(Path('parking.jpg'))
obj.run()

Resources