Last active
December 22, 2023 16:44
-
-
Save gngeorgiev/c63614b5d132ac41104ecffc2489fd6a to your computer and use it in GitHub Desktop.
opencv hell
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 numpy as np | |
import cv2 | |
def color(img): | |
imageFrame = cv2.resize(img, (0, 0), None, 0.2, 0.2) | |
# Convert the imageFrame in | |
# BGR(RGB color space) to | |
# HSV(hue-saturation-value) | |
# color space | |
hsvFrame = cv2.cvtColor(imageFrame, cv2.COLOR_BGR2HSV) | |
# Set range for red color and | |
# define mask | |
red_lower = np.array([0, 165, 60], np.uint8) | |
red_upper = np.array([7, 255, 255], np.uint8) | |
red_mask = cv2.inRange(hsvFrame, red_lower, red_upper) | |
# Set range for green color and | |
# define mask | |
green_lower = np.array([40, 70, 0], np.uint8) | |
green_upper = np.array([77, 255, 255], np.uint8) | |
green_mask = cv2.inRange(hsvFrame, green_lower, green_upper) | |
# Set range for blue color and | |
# define mask | |
blue_lower = np.array([85, 90, 70], np.uint8) | |
blue_upper = np.array([125, 255, 255], np.uint8) | |
blue_mask = cv2.inRange(hsvFrame, blue_lower, blue_upper) | |
# Morphological Transform, Dilation | |
# for each color and bitwise_and operator | |
# between imageFrame and mask determines | |
# to detect only that particular color | |
kernel = np.ones((5, 5), "uint8") | |
# For red color | |
red_mask = cv2.dilate(red_mask, kernel) | |
# For green color | |
green_mask = cv2.dilate(green_mask, kernel) | |
# For blue color | |
blue_mask = cv2.dilate(blue_mask, kernel) | |
# Creating contour to track red color | |
contours, _ = cv2.findContours(red_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
for _, contour in enumerate(contours): | |
area = cv2.contourArea(contour) | |
if area > 300: | |
x, y, w, h = cv2.boundingRect(contour) | |
imageFrame = cv2.rectangle( | |
imageFrame, (x, y), (x + w, y + h), (0, 0, 255), 2 | |
) | |
cv2.putText( | |
imageFrame, "Red", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255) | |
) | |
# Creating contour to track green color | |
contours, _ = cv2.findContours(green_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
for _, contour in enumerate(contours): | |
area = cv2.contourArea(contour) | |
if area > 300: | |
x, y, w, h = cv2.boundingRect(contour) | |
imageFrame = cv2.rectangle( | |
imageFrame, (x, y), (x + w, y + h), (0, 255, 0), 2 | |
) | |
cv2.putText( | |
imageFrame, "Green", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0) | |
) | |
# Creating contour to track blue color | |
contours, _ = cv2.findContours(blue_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) | |
for _, contour in enumerate(contours): | |
area = cv2.contourArea(contour) | |
if area > 300: | |
x, y, w, h = cv2.boundingRect(contour) | |
imageFrame = cv2.rectangle( | |
imageFrame, (x, y), (x + w, y + h), (255, 0, 0), 2 | |
) | |
cv2.putText( | |
imageFrame, "Blue", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 0, 0) | |
) | |
return "Color", imageFrame |
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 sys | |
import cv2 | |
import color | |
import size | |
def main(): | |
if len(sys.argv) < 3: | |
print("not enough arguments") | |
exit(1) | |
fn = sys.argv[1] | |
imgPath = sys.argv[2] | |
img = cv2.imread(imgPath) | |
name = "" | |
if fn == "color": | |
name, img = color.color(img) | |
elif fn == "size": | |
name, img = size.size(img) | |
else: | |
print("invalid function name") | |
exit(2) | |
cv2.imshow(name, img) | |
cv2.waitKey(0) | |
cv2.destroyAllWindows() | |
if __name__ == "__main__": | |
main() |
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 sys | |
import cv2 | |
import numpy as np | |
# upscale of the final image | |
scale = 3 | |
scalePad = 20 | |
# width and height of A4 paper in milimeters | |
width = 210 | |
height = 297 | |
# final image size | |
finalWidth = width * scale | |
finalHeight = height * scale | |
# contours drawing | |
contoursColor = (0, 255, 0) | |
contoursThickness = 2 | |
# text drawing | |
textScale = 1.5 | |
textColor = (255, 0, 255) | |
textLineWidth = 2 | |
def size(img): | |
_, data = get_contours(img) | |
if len(data) == 0: | |
print("no contours found") | |
exit(1) | |
biggestCont = largest_contour(data) | |
imgWarp = warp_img(img, biggestCont["approx"], finalWidth, finalHeight) | |
imgContours, data = get_contours(imgWarp) | |
for obj in data: | |
process_shapes_sides(imgContours, obj) | |
return "Size", imgContours | |
def process_shapes_sides(img, obj): | |
approx = obj["approx"] | |
# draw the contour lines | |
cv2.polylines(img, [approx], True, contoursColor, contoursThickness) | |
for i, _ in enumerate(approx): | |
a = approx[i] | |
b = approx[0] | |
if i < len(approx) - 1: | |
b = approx[i + 1] | |
aW = [a[0][0] // scale, a[0][1] // scale] | |
aH = [b[0][0] // scale, b[0][1] // scale] | |
length = round(find_dist(aW, aH) / 10, 1) | |
(x, y) = (a[0][0], a[0][1]) | |
cv2.putText( | |
img, | |
"{}cm".format(length), | |
(x, y), | |
cv2.FONT_HERSHEY_COMPLEX_SMALL, | |
textScale, | |
textColor, | |
textLineWidth, | |
) | |
def largest_contour(contours): | |
# Get the largest contour | |
maxArea = 0 | |
maxContours = None | |
for i in contours: | |
area = cv2.contourArea(i["cont"]) | |
if area > maxArea: | |
maxArea = area | |
maxContours = i | |
return maxContours | |
def get_contours(img, filter=0): | |
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) | |
imgCanny = cv2.Canny(imgBlur, 50, 50) | |
kernel = np.ones((5, 5)) | |
imgDial = cv2.dilate(imgCanny, kernel, iterations=3) | |
imgThre = cv2.erode(imgDial, kernel, iterations=1) | |
contours, _ = cv2.findContours(imgThre, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
finalCountours = [] | |
for i in contours: | |
peri = cv2.arcLength(i, True) | |
approx = cv2.approxPolyDP(i, 0.02 * peri, True) | |
if len(approx) == filter or filter == 0: | |
finalCountours.append( | |
{ | |
"cont": i, | |
"approx": approx, | |
"area": cv2.contourArea(i), | |
} | |
) | |
finalCountours = sorted(finalCountours, key=lambda x: x["area"], reverse=True) | |
return img, finalCountours | |
def reorder(points): | |
reordered = np.zeros_like(points) | |
points = points.reshape((4, 2)) | |
add = points.sum(1) | |
reordered[0] = points[np.argmin(add)] | |
reordered[3] = points[np.argmax(add)] | |
diff = np.diff(points, axis=1) | |
reordered[1] = points[np.argmin(diff)] | |
reordered[2] = points[np.argmax(diff)] | |
return reordered | |
def warp_img(img, points, w, h): | |
pts1 = np.float32(reorder(points)) | |
pts2 = np.float32([[0, 0], [w, 0], [0, h], [w, h]]) | |
matrix = cv2.getPerspectiveTransform(pts1, pts2) | |
imgWarp = cv2.warpPerspective(img, matrix, (w, h)) | |
return imgWarp[ | |
scalePad : imgWarp.shape[0] - scalePad, scalePad : imgWarp.shape[1] - scalePad | |
] | |
def find_dist(pts1, pts2): | |
return ((pts2[0] - pts1[0]) ** 2 + (pts2[1] - pts1[1]) ** 2) ** 0.5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment