Last active
March 3, 2020 02:54
-
-
Save pdeutsch/19a4419b054b44bc4ac0e4f3ed14e8de to your computer and use it in GitHub Desktop.
Show green blobs with rectangles around three quadrants of target
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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