InkTracker

happycoder.tech 1 rok temu

Have you ever wondered what distance the ball of a pen travels when you take your notes? Well, if so, you don’t have to wonder anymore, because OpenCV will give you a very precise answer. A light and fast script will recognize the contours (with a given cutoff accuracy), count how many pixels they occupy, and then convert the pixels to the actual length. An observation: OpenCV prefers to recognize contours from bottom to top. Any practical application of this script?

Hint: You need to know the exact pixel/mm ratio

Hint2: The animation snippet is only for visualizing purpose, the script could work faster without it.

import time import cv2 import numpy as np def preprocess_image(image_path): # Load the image and convert to grayscale image = cv2.imread(image_path) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Smoothing and binarizing the image blur = cv2.GaussianBlur(gray, (5, 5), 0) _, thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) return image, thresh def get_text_contours(thresh_image): # Finding contours on the image contours, _ = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) return contours def calculate_length(contours): # Calculating the total length of contour lines total_length = 0 for contour in contours: total_length += cv2.arcLength(contour, True) return total_length def display_contours_and_length(image, contours, total_length_mm): # Displaying contours one by one for i, contour in enumerate(contours): # Drawing a single contour in red cv2.drawContours(image, [contour], -1, (0, 0, 255), 1) # Displaying the image cv2.imshow('Contours Animation', image) cv2.waitKey(30) # Time to display the image in milliseconds before moving to the next contour # Delay for smooth animation time.sleep(0.05) # Text to be displayed text = f"Total length: {total_length_mm/1000:.2f} m" font = cv2.FONT_HERSHEY_SIMPLEX font_scale = 1 font_thickness = 2 # Calculating the size of the text text_size = cv2.getTextSize(text, font, font_scale, font_thickness)[0] # Position of the text text_x = 50 text_y = 250 # Drawing a white rectangle as a background for the text cv2.rectangle(image, (text_x, text_y - text_size[1] - 10), (text_x + text_size[0], text_y + 10), (255, 255, 255), cv2.FILLED) # Drawing the text cv2.putText(image, text, (text_x, text_y), font, font_scale, (255, 0, 255), font_thickness) # Displaying the image with text cv2.imshow('Contours Animation', image) cv2.waitKey(0) cv2.destroyAllWindows() # Image path image_path = 'example.jpg' # Image processing image, thresh = preprocess_image(image_path) # Extracting contours contours = get_text_contours(thresh) # Calculating the length of lines total_length = calculate_length(contours) # Calculating the scale actual_length_mm = 5.5 # Actual length of the ruler in mm length_in_pixels = 24 # Length of the ruler in the image in pixels scale = actual_length_mm / length_in_pixels # Scale in mm per pixel # Assuming `total_length` is the total length of contours in pixels total_length_mm = total_length * scale print("Total line length in millimeters:", total_length_mm) # Optionally: Display image with contours # Sequentially displaying contours display_contours_and_length(image.copy(), contours, total_length_mm)
Idź do oryginalnego materiału