Difference between revisions of "PhotoMath - Code"
From RoboWiki
(Created page with "Return back to project page: PhotoMath - Jakub Vojtek Python code for the PhotoMath project: <syntaxhighlight lang=python> </syn...") |
|||
Line 3: | Line 3: | ||
Python code for the PhotoMath project: | Python code for the PhotoMath project: | ||
<syntaxhighlight lang=python> | <syntaxhighlight lang=python> | ||
+ | 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() | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 11:01, 7 June 2024
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()