├── 5x5_aruco-10.svg ├── ReadMe.md ├── aruco_pic.jpg ├── measure_object_size_camera.py └── object_detector.py /5x5_aruco-10.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | Hello everyone 2 | 3 | In this repository you can find a basic and simple Object Measurement project that is work with **aruco marker**. 4 | While i don't have any camera with laser to measure the distance of the objects, I find out that i can use ArUco markers as a main measure and then use it to measure other objects in the camera. 5 | Here in the photo blow, the green line is the aruco marker and the blue line is a detected object. Also the red dot is the center of the blue box. So we can calculate the **height** and **width** of a detected box-object from there. 6 | 7 | ![](https://github.com/Ali619/Object-Detection-Size-Measurement/blob/master/aruco_pic.jpg?raw=true) 8 | 9 | 10 | # Requirements: 11 | 12 | **Important Note:** **For this project I used `opencv-contrib-python` package. If you just and only install `opencv`, you will get error.** 13 | If you still getting error after installing `opencv-contrib-python` package, you can find the solution [here](https://stackoverflow.com/questions/45972357/python-opencv-aruco-no-module-named-cv2-aruco/56867817). 14 | 15 | I put `5x5_aruco-10.svg` file to print it. But be sure that you print it by 5x5 centimiter size if you want to use the exact code that I write. If you print it with other sizes, you should change the code as well. (The part that pixels will convert to centimiters) 16 | 17 | # About the project: 18 | 19 | The program will first detect *ArUco* and draw a green line around it. Then it will calculate how many pixels that the green line have. Next it will convert the amount of pixels to Centimeter and in this way the program can measure the objects in camera. 20 | 21 | The size of ArUco (the one that i used in this project) is 5x5 centimeter. So we can divide the amount of Pixels that the camera detect by 20 and calculate the size. 22 | 23 | # How to run the project: 24 | * You should run `measure_object_size_camera.py` file 25 | 26 | I hope you guys enjoy it 👍 27 | -------------------------------------------------------------------------------- /aruco_pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ali619/Object-Detection-Size-Measurement/2ae3b1bd5b62c9e0230510bb941092ac5a449fe9/aruco_pic.jpg -------------------------------------------------------------------------------- /measure_object_size_camera.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | from object_detector import * 3 | import numpy as np 4 | 5 | # Load Aruco detector 6 | parameters = cv2.aruco.DetectorParameters_create() 7 | aruco_dict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_5X5_50) 8 | 9 | 10 | # Load Object Detector 11 | detector = detectorObj() 12 | 13 | # Load Cap 14 | cap = cv2.VideoCapture(1) # my webcam input is "1" but for you if you have only one webcam it should be "0" 15 | cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) 16 | cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) 17 | 18 | while True: 19 | _, img = cap.read() 20 | 21 | # Get Aruco marker 22 | corners, _, _ = cv2.aruco.detectMarkers(img, aruco_dict, parameters=parameters) 23 | if corners: 24 | 25 | # Draw polygon around the marker 26 | int_corners = np.int0(corners) 27 | cv2.polylines(img, int_corners, True, (0, 255, 0), 5) 28 | 29 | # Aruco Perimeter 30 | aruco_perimeter = cv2.arcLength(corners[0], True) 31 | 32 | # Pixel to cm ratio 33 | pixel_cm_ratio = aruco_perimeter / 20 #The ArUco is 5x5 so it's round will be 20 (5+5+5+5) 34 | 35 | contours = detector.detect_objects(img) 36 | 37 | # Draw objects boundaries 38 | for cnt in contours: 39 | # Get rect 40 | rect = cv2.minAreaRect(cnt) 41 | (x, y), (w, h), angle = rect 42 | 43 | # Get Width and Height of the Objects by applying the Ratio pixel to cm 44 | object_width = w / pixel_cm_ratio 45 | object_height = h / pixel_cm_ratio 46 | 47 | # Display rectangle 48 | box = cv2.boxPoints(rect) 49 | box = np.int0(box) 50 | 51 | cv2.circle(img, (int(x), int(y)), 5, (0, 0, 255), -1) 52 | cv2.polylines(img, [box], True, (255, 0, 0), 2) 53 | cv2.putText(img, "Width {} cm".format(round(object_width, 1)), (int(x - 100), int(y - 20)), cv2.FONT_HERSHEY_PLAIN, 2, (100, 200, 0), 2) 54 | cv2.putText(img, "Height {} cm".format(round(object_height, 1)), (int(x - 100), int(y + 15)), cv2.FONT_HERSHEY_PLAIN, 2, (100, 200, 0), 2) 55 | 56 | 57 | 58 | cv2.imshow("Image", img) 59 | key = cv2.waitKey(1) 60 | if key == 27: 61 | break 62 | 63 | cap.release() 64 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /object_detector.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | 3 | 4 | class detectorObj(): 5 | def __init__(self): 6 | pass 7 | 8 | def detect_objects(self, frame): 9 | # Convert Image to grayscale 10 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 11 | 12 | # Create a Mask with adaptive threshold 13 | mask = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 19, 5) 14 | 15 | # Find contours 16 | contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 17 | 18 | #cv2.imshow("mask", mask) 19 | objects_contours = [] 20 | 21 | for cnt in contours: 22 | area = cv2.contourArea(cnt) 23 | if area > 2000: 24 | #cnt = cv2.approxPolyDP(cnt, 0.03*cv2.arcLength(cnt, True), True) 25 | objects_contours.append(cnt) 26 | 27 | return objects_contours 28 | 29 | # def get_objects_rect(self): 30 | # box = cv2.boxPoints(rect) # cv2.boxPoints(rect) for OpenCV 3.x 31 | # box = np.int0(box) --------------------------------------------------------------------------------