Skip to content

Instantly share code, notes, and snippets.

@gngeorgiev
Last active December 22, 2023 16:44
Show Gist options
  • Save gngeorgiev/c63614b5d132ac41104ecffc2489fd6a to your computer and use it in GitHub Desktop.
Save gngeorgiev/c63614b5d132ac41104ecffc2489fd6a to your computer and use it in GitHub Desktop.
opencv hell
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
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()
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