diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/greyBlobDetector.py b/robots-at-robots/research/robots_at_robots/armor_color/find_contour/greyBlobDetector.py deleted file mode 100644 index 9d5b2823aaaae5b4adb98e6bcd63480187b1b528..0000000000000000000000000000000000000000 --- a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/greyBlobDetector.py +++ /dev/null @@ -1,88 +0,0 @@ -import numpy as np -import cv2 as cv -import matplotlib.pyplot as plt - -PI = 3.141592653589793238 - -class Colors: - RED = "RED" - BLUE = "BLUE" - GREY = "GREY" - -class GreyBlobDetector: - # we know that if an armor is either blue or red, it must be white except on the edges - # since the shape does not change, we can try to find white blobs with the desired features - - # threshold to be considered white; 0 = black 255 = white, TBD - WHITE_THRESHOLD = 235 - # threshold for circularity (circle = 1); TBD - # circularity = 4 * PI * AREA / (PERIMETER ^ 2) - CIRCLE_THRESHOLD = 0.5 - # threshold for concavity; the formula is area_of_blob / area_convexity_hull, TBD - CONVEX_THRESHOLD = 0.99 - # threshold for how elongated it is (called intertia in opencv), TBD (circle = 1) - INERTIA_THRESHOLD = 0.2 - # unless a robot got flipped, the lines should be pretty vertical - ANGLE_THRESHOLD = 30 - # these parameters are for the shape of the image, not sure if needed or not - WIDTH_RATIO = 0.2 # width LED / width image, TBD - HEIGHT_RATIO = 0.67 # height LED / height image, TBD - DIST_LEDS_RATIO = 0.67 # distance of the 2 LEDs / width of image, TBD - - - - def __init__(self): - pass - - def calculate_max_area(self, image): - # this basically calcultes the min / max area - # false by default unless the ai that finds the armors is consistant enough with the - # picture horizontal and vertical ratio - x, y = image.shape - return (x * GreyBlobDetector.WIDTH_RATIO)*(y * GreyBlobDetector.HEIGHT_RATIO) - - def calculate_min_area(self, image): - # needed here becase part of the vertical bars may be hidden - return self.calculate_max_area(image) / 1.5 # TBD - - def calculate_distance(self, image): - # only use this if there are 2 or more blobs detected - x, y = image.shape - return y * GreyBlobDetector.DIST_LEDS_RATIO # TBD - - # finds the contours of the LEDs and returns them - def detect_color(self, image, area = False, distance = False, already_grayscale = False): - # transform the image into black and white - # first go to grayscale then goto black white with a threshold - grey = image - if not already_grayscale: - grey = cv.cvtColor(image, cv.COLOR_BGR2GRAY) - black_white = cv.threshold(grey, GreyBlobDetector.WHITE_THRESHOLD, 255, cv.THRESH_BINARY)[1] - - # do find countours on the black white image - contours, hierarchy = cv.findContours(black_white, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) - # note : other versions of OpenCV will require image, contours, hierarchy - # now for the characteristics of the contours - retained_contours = [] - for contour in contours: - area = cv.contourArea(contour) - # circularity < threshold : is the contour NOT circular? - circularity = 4*PI*area / (len(contour) * len(contour)) - # convexity > threashold : we want the shape to be convex - convexity = area / cv.contourArea(cv.convexHull(contour)) - # opencv docs aren't very helpful on this but looks like inertia is aspect ratio - (x,y),(width,height),theta = cv.minAreaRect(contour) - # this is basically how e - inertia = width / height - - if circularity < GreyBlobDetector.CIRCLE_THRESHOLD and \ - convexity > GreyBlobDetector.CONVEX_THRESHOLD and \ - inertia < GreyBlobDetector.INERTIA_THRESHOLD and \ - theta < GreyBlobDetector.ANGLE_THRESHOLD: - retained_contours.append(contour) - - return retained_contours - -if __name__ == '__main__': - image = cv.imread("test.png") - \ No newline at end of file diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/test.png b/robots-at-robots/research/robots_at_robots/armor_color/find_contour/test.png deleted file mode 100644 index 55aa331ad1a426651e699d05f6b2f359fe0bc9fd..0000000000000000000000000000000000000000 Binary files a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/test.png and /dev/null differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/README b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/README similarity index 100% rename from robots-at-robots/research/robots_at_robots/armor_color/find_contour/README rename to robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/README diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/blobAreaDetector.py b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/blobAreaDetector.py similarity index 100% rename from robots-at-robots/research/robots_at_robots/armor_color/find_contour/blobAreaDetector.py rename to robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/blobAreaDetector.py diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/blobEdgeDetector.py b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/blobEdgeDetector.py similarity index 93% rename from robots-at-robots/research/robots_at_robots/armor_color/find_contour/blobEdgeDetector.py rename to robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/blobEdgeDetector.py index afc0cef94e7ea76bcc9d5fad25b4865beea81e83..8a54c39a58aed54978d28669e30653a039defdf8 100644 --- a/robots-at-robots/research/robots_at_robots/armor_color/find_contour/blobEdgeDetector.py +++ b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/blobEdgeDetector.py @@ -27,14 +27,14 @@ class ContourEdgeDetector: else: # we know that its either blue or red # use the edges as a mask - mask = np.zeros(image.shape[0], image.shape[1]) + mask = np.zeros((image.shape[0], image.shape[1])) cv.drawContours(mask, contours, -1, (255), 1) # applies the mask to image image[mask != 0] = (0,0,0) # transform this to hsv hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV) # note : 0,0,0 will still be 0,0,0 - colors = hsv[:,:,0] + colors = hsv[:,:,0] average = colors.sum() / (colors != 0).sum() if abs(average - ContourEdgeDetector.RED_THRESHOLD) \ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/greyBlobDetector.py b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/greyBlobDetector.py new file mode 100644 index 0000000000000000000000000000000000000000..c02ae9db0c859bb4ea44a7ea4062728f1ccf78a7 --- /dev/null +++ b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/greyBlobDetector.py @@ -0,0 +1,127 @@ +import numpy as np +import cv2 as cv +import matplotlib.pyplot as plt +# reaplce with math.pi +PI = 3.141592653589793238 + +class Colors: + RED = "RED" + BLUE = "BLUE" + GREY = "GREY" + +def debug(image): + cv.imshow("debug", image) + cv.waitKey(0) +def debug_contours(contours, image): + mask = np.zeros((image.shape[0], image.shape[1])) + cv.drawContours(mask, contours, -1, (255), 1) + cv.imshow("debug", mask) + cv.waitKey(0) + +class GreyBlobDetector: + # we know that if an armor is either blue or red, it must be white except on the edges + # since the shape does not change, we can try to find white blobs with the desired features + + # threshold to be considered white; 0 = black 255 = white, TBD + # based on a rather dim image, might change if there's an algorithm to calculate this + WHITE_THRESHOLD = 70 + + # threshold for circularity (circle = 1); TBD + # circularity = 4 * PI * AREA / (PERIMETER ^ 2) + CIRCLE_THRESHOLD = 0.55 # based on test values of 0.72, 0.8, 0.68 + + # threshold for concavity; the formula is area_of_blob / area_convexity_hull, TBD + CONVEX_THRESHOLD = 0.85 # based on values around 0.95 and 0.98 + + # threshold for how elongated it is (called intertia in opencv), TBD (circle = 1) + MIN_INERTIA = 1.1 + MAX_INERTIA = 3.5 + + # these parameters are for the shape of the image, not sure if needed or not + WIDTH_RATIO = 0.2 # width LED / width image, TBD + HEIGHT_RATIO = 0.67 # height LED / height image, TBD + DIST_LEDS_RATIO = 0.67 # distance of the 2 LEDs / width of image, TBD + + MIN_AREA = None # to be initialized to 0.02 * area of image + + def __init__(self): + pass + + def calculate_max_area(self, image): + # this basically calcultes the min / max area + # false by default unless the ai that finds the armors is consistant enough with the + # picture horizontal and vertical ratio + x, y = image.shape + return (x * GreyBlobDetector.WIDTH_RATIO)*(y * GreyBlobDetector.HEIGHT_RATIO) + + def calculate_min_area(self, image): + # needed here becase part of the vertical bars may be hidden + return self.calculate_max_area(image) / 1.5 # TBD + + def calculate_distance(self, image): + # only use this if there are 2 or more blobs detected + x, y = image.shape + return y * GreyBlobDetector.DIST_LEDS_RATIO # TBD + + # finds the contours of the LEDs and returns them + def find_contours(self, image, area = False, distance = False, already_grayscale = False): + # transform the image into black and white + # first go to grayscale then goto black white with a threshold + GreyBlobDetector.MIN_AREA = image.shape[0] * image.shape[1] * 0.02 + grey = image + if not already_grayscale: + grey = cv.cvtColor(image, cv.COLOR_BGR2GRAY) + # 0 = noir; 255 = blanc; threshold = 180 + # use HSV instead of cv.threshold + black_white = cv.threshold(grey, GreyBlobDetector.WHITE_THRESHOLD, 255, cv.THRESH_BINARY)[1] + # do find countours on the black white image + contours, hierarchy = cv.findContours(black_white, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) + # note : other versions of OpenCV will require image, contours, hierarchy + # now for the characteristics of the contours + + retained_contours = [] + for contour in contours: + # TODO : something wrong here, probably with area + area = cv.contourArea(contour) + if area >= GreyBlobDetector.MIN_AREA: + # circularity < threshold : is the contour NOT circular? + circularity = 4*PI*area / (cv.arcLength(contour, True) * cv.arcLength(contour, True)) + # convexity > threashold : we want the shape to be convex + convexity = area / cv.contourArea(cv.convexHull(contour)) + # opencv docs aren't very helpful on this but looks like inertia is aspect ratio + (x,y),(width,height),theta = cv.minAreaRect(contour) + # this is basically aspect ratio + inertia = width / height + # note : the angle is pretty much useless + + print("calculated circularity : ", circularity) + print("threshold circularity : ", GreyBlobDetector.CIRCLE_THRESHOLD) + print() + print("calculated converxity : ", convexity) + print("threshold converxity : ", GreyBlobDetector.CONVEX_THRESHOLD) + print() + print("calculated inertia : ", inertia) + print("threshold inertia : ", GreyBlobDetector.MIN_INERTIA, GreyBlobDetector.MAX_INERTIA) + print() + print("minimal area : ", GreyBlobDetector.MIN_AREA) + print("calculated area : ", area) + # cv.SimpleBlobDetector + if circularity > GreyBlobDetector.CIRCLE_THRESHOLD and \ + convexity > GreyBlobDetector.CONVEX_THRESHOLD and \ + inertia > GreyBlobDetector.MIN_INERTIA and \ + inertia < GreyBlobDetector.MAX_INERTIA: + retained_contours.append(contour) + print("retained !") + else: + print("rejected !") + print("----------------------------------") + + # use HSV instead + # 1. color = red or blue + # use the other 2 to see if its gray + return retained_contours + +if __name__ == '__main__': + image = cv.imread("test6.PNG") + gbd = GreyBlobDetector() + print(len(gbd.find_contours(image))) diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test1.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test1.PNG new file mode 100644 index 0000000000000000000000000000000000000000..032145f4f8fa034f816137d7405ee49751810e42 Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test1.PNG differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test2.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test2.PNG new file mode 100644 index 0000000000000000000000000000000000000000..e57467cdfa1d84ca0e8138f9814c8ad11014d759 Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test2.PNG differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test3.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test3.PNG new file mode 100644 index 0000000000000000000000000000000000000000..01f8ac81b73be430c1f23f38556847d50f91f48b Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test3.PNG differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test4.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test4.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1eeebe99c07d7928a574442a9cefb5a005454211 Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test4.PNG differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test5.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test5.PNG new file mode 100644 index 0000000000000000000000000000000000000000..91e136b7c9dd94a64f5aef972060c6fabf20a531 Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test5.PNG differ diff --git a/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test6.PNG b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test6.PNG new file mode 100644 index 0000000000000000000000000000000000000000..777b4f36b2a454e45badb5ed0b4f4064774f148c Binary files /dev/null and b/robots-at-robots/research/robots_at_robots/armor_color/find_contour_blackwhite/test6.PNG differ