Skip to content

Instantly share code, notes, and snippets.

@pdeutsch
Last active March 3, 2020 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdeutsch/19a4419b054b44bc4ac0e4f3ed14e8de to your computer and use it in GitHub Desktop.
Save pdeutsch/19a4419b054b44bc4ac0e4f3ed14e8de to your computer and use it in GitHub Desktop.
Show green blobs with rectangles around three quadrants of target
import cv2
import numpy as np
import math
import argparse
res = np.array([0])
# the following will:
# - find a green blob
# - find a contour around it
# - find a rectangle around the contour
# - extract a portion of the image for that rectangle
# - split the rectangle into three parts
# - find the contour and minAreaRect of each part
#
# The left part usually has an angle of around -30 degrees
# The middle part should be close to 0 degrees, but often isn't
# The right part usually has an angle around -60 degrees
#
def proc_part(part):
contours2, hier2 = cv2.findContours(part, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(contours2) > 0:
cont2 = contours2[0]
rect = cv2.minAreaRect(cont2)
print(f"RECT: {rect}")
box = cv2.boxPoints(rect)
box = np.int0(box)
return box
return []
def proc_img(mask, img):
global res
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
hexes = []
res = cv2.bitwise_and(img, img, mask=mask)
# debug code to show some contours for frame 100
#print(f"Got contours, count: {len(contours)}")
#print(contours)
#img = cv2.drawContours(img, contours, -1, (0,255,255), 2)
for cont in contours:
x, y, w, h = cv2.boundingRect(cont)
# only process larger areas with at least 5 points in the contour
if (len(cont) > 4 and w > 40 and h > 40):
quarter_w = int(w * 0.28)
x0 = x
y0 = y
x1 = x + quarter_w
y1 = y + h
x2 = x + w - quarter_w
x3 = x + w
cv2.rectangle(img, (x0,y0), (x1, y1), (255,255,0), 2)
cv2.rectangle(img, (x1,y0), (x2, y1), (255,255,0), 2)
cv2.rectangle(img, (x2,y0), (x3, y1), (255,255,0), 2)
part1 = mask[y0:y1, x0:x1]
box1 = proc_part(part1)
box1a = box1 + [x0, y0]
#print(f"{x0:3d}/{y0:3d} box1: {box1a}")
img = cv2.drawContours(img, [box1a], 0, (0,200,255), 1)
part2 = mask[y0:y1, x1:x2]
box2 = proc_part(part2)
box2a = box2 + [x1, y0]
#print(f"box2: {box2a}")
img = cv2.drawContours(img, [box2a], 0, (200,200,155), 1)
part3 = mask[y0:y1, x2:x3]
box3 = proc_part(part3)
box3a = box3 + [x2, y0]
#print(f"box3: {box3a}")
img = cv2.drawContours(img, [box3a], 0, (0,200,155), 1)
hexes.append(cont)
#imgx = cv2.resize(img[y:y+h, x:x+w], None, fx=4.0, fy=4.0)
#cv2.imshow('imgx', imgx)
else:
print(f"ELSE: bounding rect x y w h: {x:3d} {y:3d} {w:3d} {h:3d}")
img = cv2.drawContours(img, hexes, -1, (0,0,255), 1)
return img
def show_frame(img, res, mask):
cv2.imshow('orig', img)
cv2.imshow('res', res)
cv2.imshow('mask', mask)
img2 = cv2.resize(img, None, fx=2.0, fy=2.0)
cv2.imwrite('testx.jpg', img2)
ch = cv2.waitKey(20000) & 0xff
def process_pic(fname):
upper_green = np.array([79,255,255])
lower_green = np.array([58,50,100])
cv2.namedWindow('orig')
cv2.namedWindow('res')
cv2.namedWindow('mask')
cv2.moveWindow('orig', 0, 0)
cv2.moveWindow('res', 600, 0)
cv2.moveWindow('mask', 300, 500)
quit_flag = False
ratio = -1
img = cv2.imread(fname, cv2.IMREAD_COLOR)
if ratio < 0:
ratio = 640.0 / img.shape[1]
print(f"ratio = {ratio}")
img = cv2.resize(img, None, fx=ratio, fy=ratio)
# blur to get try to remove missing parts
img = cv2.GaussianBlur(img, (5,5), 0)
hsvimg = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsvimg, lower_green, upper_green)
# mask out the bottom of the image
mask[250:,:] = 0
img = proc_img(mask, img)
show_frame(img, res, mask)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('fname', help='Video filename', nargs='+')
args = parser.parse_args()
for video_fname in args.fname:
process_pic(video_fname)
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment