PhotoMath - Code

From RoboWiki
Jump to: navigation, search

Return back to project page: PhotoMath - Jakub Vojtek

Python code for the PhotoMath project:

 
import cv2
import pytesseract
from buildhat import Motor, ForceSensor
import time
import re
import numpy as np
from datetime import datetime

motor_a = Motor('A')
button = ForceSensor('D')

doors_open = True

cam_width = 320
cam_height = 240
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, cam_width)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT, cam_height)

# Path to Tesseract executable (change this according to your installation)
pytesseract.pytesseract.tesseract_cmd = '/usr/bin/tesseract'


def close_doors(force):
    global doors_open
    if doors_open:
        motor_a.run_for_degrees(720, 10)
        doors_open = False
        time.sleep(3)
        process_and_open_door()
    else:
        pass

button.when_pressed = close_doors


def read_text(image):
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    text = pytesseract.image_to_string(gray, config='--psm 6')
    return text


def preprocess_expression(expression):
    expression = expression.replace('\n', '').strip()
    expression = re.sub(r'(?<=[^\s\(\)]) (?=[^\s\(\)])', ' ', expression)
    expression = re.sub(r'(?<=[^\s\(\)])[\+\-\*/\(\)](?=[^\s\(\)])', ' \\g<0> ', expression)
    return expression


def validate_expression(expression):
    return re.match(r'^[\d\s\+\-\*/\(\)]+$', expression)


def simple_calculator(expression):
    try:
        result = round(eval(expression), 4)
        return result
    except Exception as e:
        return "Error: {}".format(str(e))


def process_and_open_door():
    global doors_open
    ret, frame = camera.read()
    frame = frame[cam_height // 2 - 45: cam_height - 90, :cam_width - 70]
    text = read_text(frame)
    print("Extracted text:", text.encode('utf-8'))
    expression = preprocess_expression(text)
    if validate_expression(expression):
        result = simple_calculator(expression)
        print("Solution: ", result)
        annotate_and_save_image(frame, text, result)
    else:
        print("Invalid expression")
    motor_a.run_for_degrees(720, 10)  # Open the door again
    doors_open = True


def annotate_and_save_image(image, text, result):
    timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
    annotated_image = image.copy()
    cv2.putText(annotated_image, f"Text: {text}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
    cv2.putText(annotated_image, f"Result: {result}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
    filename = f"equation_{timestamp}.png"
    cv2.imwrite(filename, annotated_image)
    print(f"Saved image: {filename}")


if __name__ == '__main__':
    while True:
        ret, frame = camera.read()

        frame = frame[cam_height // 2 - 45: cam_height - 90, :cam_width - 70]
        cv2.imshow("Camera", frame)

        key = cv2.waitKey(1) & 0xFF

        # Exit loop if 'q' is pressed
        if key == ord('q'):
            break

    camera.release()
    cv2.destroyAllWindows()