Spaces:
Runtime error
Runtime error
import sys | |
import os | |
sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) | |
from paddleocr import PaddleOCR | |
import cv2 | |
import numpy as np | |
import pandas as pd | |
from doctr.models import ocr_predictor | |
from torch.utils.data import DataLoader | |
from doctr.io import DocumentFile | |
import math | |
from typing import Tuple, Union | |
import cv2 | |
import numpy as np | |
import os | |
from deskew import determine_skew | |
print(sys.version) | |
ocr = PaddleOCR(lang='en') | |
model = ocr_predictor(pretrained=True) | |
ocr = PaddleOCR(lang='en') | |
def find_surr_keys(unassigned_key, known_keys): | |
# Sort known keys | |
print(known_keys) | |
known_keys = sorted(known_keys) | |
# Initialize distances and closest keys | |
closest_keys = [] | |
for k in known_keys: | |
closest_keys.append((abs(int(k) - int(unassigned_key)), k)) | |
# Sort by distance | |
closest_keys.sort() | |
# Return the two closest known keys | |
if(closest_keys[0][1]<unassigned_key and closest_keys[0][1]>unassigned_key): | |
return [closest_keys[0][1], closest_keys[1][1]] | |
else: | |
raise ValueError(f"No closest keys found for unassigned key: {unassigned_key}") | |
def label_text(text): | |
# Define the two lists | |
list1 = ['t', 'r', 'u', 'T', 'R', 'U'] | |
list2 = ['f', 'a', 'l', 's', 'F', 'A', 'L', 'S'] | |
# Count the matches for each list | |
count1 = sum(text.count(char) for char in list1) | |
count2 = sum(text.count(char) for char in list2) | |
# Determine the label based on the counts | |
if count1 > count2: | |
return True | |
elif count1!=0 or count2!=0: | |
return False | |
def percentMatch(text1,text2): | |
list = ['t', 'r', 'u', 'T', 'R', 'U','f', 'a', 'l', 's', 'F', 'A', 'L', 'S'] | |
if(text1): | |
count1 = sum(text1.count(char) for char in list) | |
count2 = sum(text2.count(char) for char in list) | |
if(count1==3 and count2==4 or count1==4 and count2==3 ): #if one says true and other says false then priority given to 2nd | |
print("true and false collision so given priority to text2 which is the incoming text") | |
return 2 | |
if(count1>count2): | |
print("text1 i.e the prev text is the winner") | |
return 1 | |
else: | |
print("text2 i.e the incoming text is the winner") | |
return 2 | |
else: | |
print("text1 not there so text2 is the winner") | |
return 2 | |
def count_true_false(d): #in a dictionary to check how many T/F are there. | |
true_count = sum(1 for v in d.values() if v is True) | |
false_count = sum(1 for v in d.values() if v is False) | |
return true_count, false_count | |
def merge_dicts(dict1, dict2): | |
true_count1, false_count1 = count_true_false(dict1) | |
true_count2, false_count2 = count_true_false(dict2) | |
if (true_count1 + false_count1) >= (true_count2 + false_count2): | |
final_dict = dict1.copy() | |
y_dirn_gap=False | |
else: | |
final_dict = dict2.copy() | |
y_dirn_gap=True | |
return final_dict,y_dirn_gap | |
def assign_true_false_or_unknown(true_list, false_list, question_dict,total_questions): | |
# Initialize the final dictionary | |
final_dict = {str(i): 'UNASSIGNED' for i in range(1, total_questions+1)} | |
unassigned_keys=[] | |
assigned_keys=[] | |
# Iterate over each question and its y-coordinate | |
for question, y in question_dict.items(): | |
# compute diff with true list such that we sub t/f box from s/n box | |
# true_differences= [y - ty for ty in true_list] | |
# Compute absolute differences with true list | |
true_abs_differences = [abs(y - ty) for ty in true_list] | |
# Compute absolute differences with false list | |
# false_differences= [y - ty for ty in false_list] | |
false_abs_differences = [abs(y - fy) for fy in false_list] | |
# Find the minimum differences | |
# min_true_diff = min((diff for diff in true_differences if diff > 0), default=float('inf')) | |
# min_false_diff = min((diff for diff in false_differences if diff > 0), default=float('inf')) | |
min_true_abs_diff=min(true_abs_differences) if true_abs_differences else float('inf') | |
min_false_abs_diff=min(false_abs_differences) if false_abs_differences else float('inf') | |
# Determine the smallest difference | |
# min_diff = min(min_true_diff, min_false_diff) | |
min_abs_diff=min(min_true_abs_diff,min_false_abs_diff) | |
# Assign the value based on the smallest difference | |
# if min_diff < 360: | |
# if min_true_diff < min_false_diff: | |
# final_dict[question] = True | |
# true_list.pop(true_differences.index(min_true_diff)) | |
# else: | |
# final_dict[question] = False | |
# false_list.pop(false_differences.index(min_false_diff)) | |
# else: | |
# checking the abs diff option if nothing can find in positive diff option | |
if min_abs_diff < 300: | |
if min_true_abs_diff < min_false_abs_diff: | |
final_dict[question] = True | |
true_list.pop(true_abs_differences.index(min_true_abs_diff)) | |
else: | |
final_dict[question] = False | |
false_list.pop(false_abs_differences.index(min_false_abs_diff)) | |
else: | |
final_dict[question] = 'NULL' | |
return final_dict | |
def assign_true_false_or_unknown_rotated(true_list,false_list,true_list_x,false_list_x,question_dict,question_dict_x,total_questions): | |
final_dict = {str(i): 'UNASSIGNED' for i in range(1, total_questions+1)} | |
unassigned_keys=[] | |
assigned_keys=[] | |
final_dict_y={str(i): 'UNASSIGNED' for i in range(1, total_questions+1)} | |
final_dict_x={str(i): 'UNASSIGNED' for i in range(1, total_questions+1)} | |
# Iterate over each question and its y-coordinate | |
for question, y in question_dict.items(): | |
# Compute absolute differences with true list | |
true_differences= [y - ty for ty in true_list] | |
true_abs_differences = [abs(y - ty) for ty in true_list] | |
# Compute absolute differences with false list | |
false_differences= [y - fy for fy in false_list] | |
false_abs_differences = [abs(y - fy) for fy in false_list] | |
# Find the minimum differences | |
min_true_diff = min((diff for diff in true_differences if diff > 0), default=float('inf')) | |
min_false_diff = min((diff for diff in false_differences if diff > 0), default=float('inf')) | |
min_true_abs_diff=min(true_abs_differences) if true_abs_differences else float('inf') | |
min_false_abs_diff=min(false_abs_differences) if false_abs_differences else float('inf') | |
# Determine the smallest difference | |
min_diff = min(min_true_diff, min_false_diff) | |
min_abs_diff=min(min_true_abs_diff,min_false_abs_diff) | |
# print("the question number is :",question) | |
# print("the min dist is :",min_diff) | |
# print("the min abs_diff is :",min_abs_diff) | |
# print("the false abs diff",false_abs_differences) | |
# Assign the value based on the smallest difference first going with abs diff as for upside down it will favour abs | |
if min_abs_diff < 310: | |
if min_true_abs_diff < min_false_abs_diff: | |
final_dict_y[question] = True | |
true_list.pop(true_abs_differences.index(min_true_abs_diff)) | |
else: | |
final_dict_y[question] = False | |
false_list.pop(false_abs_differences.index(min_false_abs_diff)) | |
else: | |
# checking the postive diff option if nothing can find in abs diff option | |
if min_diff < 310: | |
print(question) | |
if min_true_diff < min_false_diff: | |
final_dict_y[question] = True | |
true_list.pop(true_differences.index(min_true_diff)) | |
else: | |
final_dict_y[question] = False | |
false_list.pop(false_differences.index(min_false_diff)) | |
else: | |
final_dict_y[question] = 'NULL' | |
for question,x in question_dict_x.items(): | |
# Compute absolute differences with true list | |
true_differences= [x - tx for tx in true_list_x] | |
true_abs_differences = [abs(x - tx) for tx in true_list_x] | |
# Compute absolute differences with false list | |
false_differences= [x - fy for fy in false_list_x] | |
false_abs_differences = [abs(x - fy) for fy in false_list_x] | |
# Find the minimum differences | |
min_true_diff = min((diff for diff in true_differences if diff > 0), default=float('inf')) | |
min_false_diff = min((diff for diff in false_differences if diff > 0), default=float('inf')) | |
min_true_abs_diff=min(true_abs_differences) if true_abs_differences else float('inf') | |
min_false_abs_diff=min(false_abs_differences) if false_abs_differences else float('inf') | |
# Determine the smallest difference | |
min_diff = min(min_true_diff, min_false_diff) | |
min_abs_diff=min(min_true_abs_diff,min_false_abs_diff) | |
if min_diff < 310: | |
if min_true_diff < min_false_diff: | |
final_dict_x[question] = True | |
true_list_x.pop(true_differences.index(min_true_diff)) | |
else: | |
final_dict_x[question] = False | |
false_list_x.pop(false_differences.index(min_false_diff)) | |
else: | |
# checking the abs diff option if nothing can find in positive diff option | |
if min_abs_diff < 310: | |
if min_true_abs_diff < min_false_abs_diff: | |
final_dict_x[question] = True | |
true_list_x.pop(true_abs_differences.index(min_true_abs_diff)) | |
else: | |
final_dict_x[question] = False | |
false_list_x.pop(false_abs_differences.index(min_false_abs_diff)) | |
else: | |
final_dict_x[question] = 'NULL' | |
print("the final dict for y is: ") | |
print(final_dict_y) | |
print("the final dict for x is: ") | |
print(final_dict_x) | |
final_dict,y_dirn_gap=merge_dicts(final_dict_x,final_dict_y) | |
if 'L' in final_dict: | |
final_dict['7']=final_dict['L'] | |
del final_dict['L'] | |
if 'I' in final_dict: | |
final_dict['1']=final_dict['I'] | |
del final_dict['I'] | |
if y_dirn_gap and '6' in final_dict and '9' in final_dict: #means image is inverted and 6 and 9 true and false value needs to swapped out | |
temp=final_dict['6'] | |
final_dict['6']=final_dict['9'] | |
final_dict['9']=temp | |
return final_dict | |
def process_using_paddleocr(image_path,output_folder,output_folder1,total_questions): | |
ocr = PaddleOCR(lang='en') | |
base_name = os.path.basename(image_path) | |
image_cv = cv2.imread(image_path) | |
print("!------------------------------start with paddleocr-----------------------------------!") | |
print("Started processing of the image :",base_name) | |
output = ocr.ocr(image_path)[0] | |
texts = [line[1][0] for line in output] | |
print("OCR detection done") | |
boxes = [line[0] for line in output] | |
# probabilities = [line[1][1] for line in output] | |
image_boxes = image_cv.copy() | |
# print("!------------------------------all coordinates-----------------------------------!") | |
for box,text in zip(boxes,texts): | |
cv2.rectangle(image_boxes,(int(box[0][0]),int(box[0][1])),(int(box[2][0]),int(box[2][1])),(0,0,255),5) #needs top left and bottom right to draw bounding box | |
cv2.putText(image_boxes,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,4,(222,0,0),3) | |
alldet_file_name = f'detect_{base_name}' | |
alldet_file_path = os.path.join(output_folder1, alldet_file_name) | |
# Save the processed image | |
cv2.imwrite(alldet_file_path, image_boxes) | |
for box, text in zip(boxes, texts): | |
if text=="SN" or text=="NS": | |
num_l_x1=box[0][0] | |
num_r_x1=box[2][0]+140 | |
num_l_y1=box[0][1] | |
num_r_y1=box[2][1]+140 | |
print("left top x of SN:",num_l_x1) | |
print("bottom right x of SN:",num_r_x1) | |
print("left top y of SN:",num_l_y1) | |
print("bottom right y of SN:",num_r_y1) | |
cons_boxes_image=image_cv.copy() | |
true_list=[] | |
false_list=[] | |
true_list_x=[] | |
false_list_x=[] | |
numbers_dict={} | |
numbers_dict_x={} | |
c=0 | |
prev_x=0 | |
prev_y=0 | |
# this is for s/n column | |
try: | |
for box, text in zip(boxes, texts): | |
# print(f"the text is : {text}") | |
box_top_left_x = int(box[0][0]) | |
box_top_left_y=int(box[0][1]) | |
box_bottom_right_x = int(box[2][0]) | |
box_bottom_right_y = int(box[2][1]) | |
box_width_x = box_bottom_right_x - box_top_left_x | |
box_width_y = box_bottom_right_y - box_top_left_y | |
if (num_l_x1 <= box_bottom_right_x <= num_r_x1 or num_l_y1<= box_bottom_right_y<=num_r_y1) and box_width_x <= 200 and box_width_y <= 200 and text!="SN" and text!="NS": | |
# print("entered in the S/N column ") | |
# print(text) | |
# print(box) | |
numbers_dict[text] = int(box[0][1]) | |
numbers_dict_x[text]=int(box[0][0]) | |
cv2.rectangle(cons_boxes_image, (int(box[0][0]), int(box[0][1])), (int(box[2][0]), int(box[2][1])), (0, 0, 255), 5) | |
cv2.putText(cons_boxes_image, text, (int(box[0][0]), int(box[0][1])), cv2.FONT_HERSHEY_SIMPLEX, 4, (222, 0, 0), 1) | |
#error in detection of S/N column | |
except NameError: | |
print("cant detect s/n column also so going with all detection using box width") | |
c=0 | |
for box,text in zip(boxes,texts): | |
box_top_left_x = int(box[0][0]) | |
box_top_left_y=int(box[0][1]) | |
box_bottom_right_x = int(box[2][0]) | |
box_bottom_right_y = int(box[2][1]) | |
box_width_x = box_bottom_right_x - box_top_left_x | |
box_width_y = box_bottom_right_y - box_top_left_y | |
if (box_width_x <= 80 and box_width_y <= 80): | |
if text.isdigit(): | |
number = int(text) | |
if 1 <= number <= total_questions+1: | |
# Store in dictionaries only if the number is between 1 and 10 | |
numbers_dict[text] = int(box[0][1]) | |
numbers_dict_x[text] = int(box[0][0]) | |
# Visualize the rectangle and text on the image (optional) | |
cv2.rectangle(cons_boxes_image, (int(box[0][0]), int(box[0][1])), (int(box[1][0]), int(box[1][1])), (0, 0, 255), 5) | |
cv2.putText(cons_boxes_image, text, (int(box[0][0]), int(box[0][1])), cv2.FONT_HERSHEY_SIMPLEX, 4, (222, 0, 0), 1) | |
if((box_width_x<=300 and box_width_y<=300) and ' ' not in text and label_text(text)==True): | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev_y=box[0][1] | |
prev_x=box[0][0] | |
true_list.append(int(box[0][1])) | |
true_list_x.append(int(box[0][0])) | |
else: | |
if((abs(box[0][0]-prev_x)>160) or abs(box[0][1]-prev_y)>160): | |
print(text) | |
print(box) | |
true_list.append(int(box[0][1])) | |
true_list_x.append(int(box[0][0])) | |
prev_y=box[0][1] | |
prev_x=box[0][0] | |
c+=1 | |
cv2.rectangle(cons_boxes_image,(int(box[0][0]),int(box[0][1])),(int(box[2][0]),int(box[2][1])),(0,0,255),5) | |
cv2.putText(cons_boxes_image,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,4,(222,0,0),1) | |
if((box_width_x<=300 and box_width_y<=300) and ' ' not in text and label_text(text)==False): | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev_y=box[0][1] | |
prev_x=box[0][0] | |
false_list.append(int(box[0][1])) | |
false_list_x.append(int(box[0][0])) | |
else: | |
if((abs(box[0][0]-prev_x)>160) or abs(box[0][1]-prev_y)>160): | |
print(text) | |
print(box) | |
false_list.append(int(box[0][1])) | |
false_list_x.append(int(box[0][0])) | |
prev_y=box[0][1] | |
prev_x=box[0][0] | |
c+=1 | |
cv2.rectangle(cons_boxes_image,(int(box[0][0]),int(box[0][1])),(int(box[2][0]),int(box[2][1])),(0,0,255),5) | |
cv2.putText(cons_boxes_image,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,4,(222,0,0),1) | |
print("the number dict is: ",numbers_dict) | |
print("the number dict x is: ",numbers_dict_x) | |
print("the true list is ",true_list) | |
print("the false list is ",false_list) | |
print("the true list for xdirn",true_list_x) | |
print("the false list for xdirn",false_list_x) | |
final_dict=assign_true_false_or_unknown_rotated(true_list,false_list,true_list_x,false_list_x,numbers_dict,numbers_dict_x,total_questions) | |
# Create a unique output file name | |
output_file_name = f'final_tf_{base_name}' | |
output_file_path = os.path.join(output_folder, output_file_name) | |
# Save the processed image | |
cv2.imwrite(output_file_path, cons_boxes_image) | |
return final_dict | |
def rotate( | |
image: np.ndarray, angle: float, background: Union[int, Tuple[int, int, int]] | |
) -> np.ndarray: | |
old_width, old_height = image.shape[:2] | |
angle_radian = math.radians(angle) | |
width = abs(np.sin(angle_radian) * old_height) + abs(np.cos(angle_radian) * old_width) | |
height = abs(np.sin(angle_radian) * old_width) + abs(np.cos(angle_radian) * old_height) | |
image_center = tuple(np.array(image.shape[1::-1]) / 2) | |
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0) | |
rot_mat[1, 2] += (width - old_width) / 2 | |
rot_mat[0, 2] += (height - old_height) / 2 | |
return cv2.warpAffine(image, rot_mat, (int(round(height)), int(round(width))), borderValue=background) | |
def process_using_doctr_less_row_gap(boxes,texts,numbers_dict,num_l_x2,num_r_x2,image_path,total_questions): | |
print("the number dict in low gap",numbers_dict) | |
cons_boxes_image = cv2.imread(image_path) | |
true_list=[] | |
false_list=[] | |
c=0 | |
print("starting with low row gap") | |
try: | |
for box, text in zip(boxes, texts): | |
box_bottom_right_x = int(box[1][0]) | |
# Draw the adjusted bounding box | |
if (num_l_x2 <= box_bottom_right_x <= num_r_x2): | |
# print("entered in the t/f column ") | |
if label_text(text)==True and text!='TRUE/FALSE': | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev=box[0][1] | |
prev_text=text | |
true_list.append(int(box[0][1])) | |
else: | |
if(abs(box[0][1]-prev)>20): #to avoid boxes in same row to overlap | |
print(text) | |
print(box) | |
true_list.append(int(box[0][1])) | |
prev=box[0][1] | |
prev_text=text | |
else: | |
print(f"collision happend with box:{prev} and text:{prev_text} solving on the basis of percent match boxes") | |
print("the current box specification are") | |
print(text) | |
print(box) | |
ans=percentMatch(prev_text,text) | |
if(ans==2): | |
if(label_text(prev_text)==False): | |
false_list.pop() | |
elif(label_text(prev_text)==True): | |
true_list.pop() | |
prev=box[0][1] | |
prev_text=text | |
true_list.append(int(prev)) | |
c+=1 | |
elif label_text(text)==False and text!='TRUE/FALSE': | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev=box[0][1] | |
prev_text=text | |
false_list.append(int(box[0][1])) | |
else: | |
if(abs(box[0][1]-prev)>20): | |
print(text) | |
print(box) | |
false_list.append(int(box[0][1])) | |
prev=box[0][1] | |
prev_text=text | |
else: | |
print(f"collision happend with box:{prev} and text:{prev_text} solving on the basis of percent match boxes") | |
print("the current box specification are") | |
print(text) | |
print(box) | |
ans=percentMatch(prev_text,text) | |
if(ans==2): | |
if(label_text(prev_text)==False): | |
false_list.pop() | |
elif(label_text(prev_text)==True): | |
true_list.pop() | |
prev=box[0][1] | |
prev_text=text | |
false_list.append(int(prev)) | |
c+=1 | |
cv2.rectangle(cons_boxes_image,(int(box[0][0]),int(box[0][1])),(int(box[1][0]),int(box[1][1])),(0,0,255),5) | |
cv2.putText(cons_boxes_image,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,1,(222,0,0),1) | |
final_dict=assign_true_false_or_unknown(true_list,false_list,numbers_dict,total_questions) | |
return cons_boxes_image,final_dict | |
except Exception as e: | |
print("error occured") | |
print(e) | |
def process_and_save_image(image_path,actual_ans_csv ,output_folder , output_folder1): | |
base_name = os.path.basename(image_path) | |
image_cv = cv2.imread(image_path) | |
height = image_cv.shape[0] | |
width = image_cv.shape[1] | |
print("!------------------------------starting detection using doctr-----------------------------------!") | |
print("Started processing of the image :",base_name) | |
# print(image_width) | |
# output = ocr.ocr(image_path)[0] | |
# checking if header is there | |
with open(actual_ans_csv, 'r') as file: | |
first_line = file.readline().strip() | |
# Check if the first column of the first line is numeric | |
first_column_numeric = False | |
try: | |
first_value = float(first_line.split(',')[0]) # Assuming comma-separated values | |
first_column_numeric = True | |
except ValueError: | |
pass # If the first column cannot be converted to a float, it's not numeric | |
# Read the CSV file based on the condition | |
if first_column_numeric: | |
actualAns_df = pd.read_csv(actual_ans_csv, header=None) | |
else: | |
actualAns_df = pd.read_csv(actual_ans_csv) | |
total_questions = len(actualAns_df) | |
#checking skewness | |
grayscale = cv2.cvtColor(image_cv, cv2.COLOR_BGR2GRAY) | |
angle = determine_skew(grayscale) | |
image_cv = rotate(image_cv, angle, (0, 0, 0)) | |
cv2.imwrite(image_path, image_cv) | |
single_img_doc = DocumentFile.from_images(image_path) | |
result = model(single_img_doc) | |
texts=[] | |
for page in result.pages: | |
for block in page.blocks: | |
for line in block.lines: | |
for word in line.words: | |
text = word.value | |
texts.append(text) | |
#checking for rotation | |
r_count=0 | |
while('TRUE/FALSE' not in texts): | |
image_cv = cv2.rotate(image_cv, cv2.ROTATE_90_CLOCKWISE) | |
print("rotation started") | |
# Save the rotated image to a temporary path | |
# temp_image_path = 'temp_rotated_image.jpg' | |
cv2.imwrite(image_path, image_cv) | |
# output=ocr.ocr(temp_image_path)[0] | |
single_img_doc = DocumentFile.from_images(image_path) | |
result=model(single_img_doc) | |
texts=[] | |
for page in result.pages: | |
for block in page.blocks: | |
for line in block.lines: | |
for word in line.words: | |
text = word.value | |
texts.append(text) | |
print(texts) | |
r_count+=1 | |
if r_count==4: #reaching the same orientation | |
break | |
if(r_count>0 and r_count!=4): | |
# cv2.imwrite(image_path,image_cv) | |
print("rotation done for: ",base_name) | |
print("Number of times rotation done:",r_count) | |
height = image_cv.shape[0] | |
width = image_cv.shape[1] | |
print("OCR detection done with doctr") | |
boxes=[] | |
# boxes = [line[0] for line in output]4 | |
for page in result.pages: | |
for block in page.blocks: | |
for line in block.lines: | |
for word in line.words: | |
(x_min, y_min), (x_max, y_max) = word.geometry | |
x_min_px = x_min * width | |
y_min_px = y_min * height | |
x_max_px = x_max * width | |
y_max_px = y_max * height | |
bbox=(x_min_px, y_min_px), (x_max_px, y_max_px) | |
boxes.append(bbox) | |
image_boxes = image_cv.copy() | |
# print("!------------------------------all coordinates-----------------------------------!") | |
for box,text in zip(boxes,texts): | |
# print(text) | |
# print(box) | |
cv2.rectangle(image_boxes,(int(box[0][0]),int(box[0][1])),(int(box[1][0]),int(box[1][1])),(0,0,255),5) #needs top left and bottom right to draw bounding box | |
cv2.putText(image_boxes,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,4,(222,0,0),3) | |
# print("!------------------------------done with all coordinates-----------------------------------!") | |
alldet_file_name = f'detect_{base_name}' | |
alldet_file_path = os.path.join(output_folder1, alldet_file_name) | |
# Save the processed image | |
cv2.imwrite(alldet_file_path, image_boxes) | |
for box, text in zip(boxes, texts): | |
if text=="SN" or text=="NS": | |
num_l_x1=box[0][0]-100 | |
num_r_x1=box[1][0]+140 | |
print("left top x of SN:",num_l_x1) | |
print("bottom right x of SN:",num_r_x1) | |
if text=="TRUE/FALSE": | |
num_l_x2=box[0][0]-10 | |
num_r_x2=box[1][0]+200 | |
print("left top x of T/F:",num_l_x2) | |
print("bottom right x of T/F:",num_r_x2) | |
# Draw OCR bounding boxes within the final rectangle | |
cons_boxes_image=image_cv.copy() | |
true_list=[] | |
false_list=[] | |
numbers_dict={} | |
numbers_dict_x={} | |
c=0 | |
no_of_collisions=0 | |
try: | |
# this is for s/n column | |
for box, text in zip(boxes, texts): | |
# print(f"the text is : {text}") | |
box_top_left_x = int(box[0][0]) | |
box_top_left_y=int(box[0][1]) | |
box_bottom_right_x = int(box[1][0]) | |
box_bottom_right_y = int(box[1][1]) | |
# print(box_bottom_right_x) | |
# print(box_bottom_right_y) | |
# print(box_width_x) | |
# print(box_width_y) | |
if (num_l_x1 <= box_bottom_right_x <= num_r_x1 ): | |
if text.isdigit(): | |
number = int(text) | |
if 1 <= number <= total_questions+1: | |
# Store in dictionaries only if the number is between 1 and 10 | |
numbers_dict[text] = int(box[0][1]) | |
print(text) | |
print(box) | |
# Visualize the rectangle and text on the image (optional) | |
cv2.rectangle(cons_boxes_image, (int(box[0][0]), int(box[0][1])), (int(box[1][0]), int(box[1][1])), (0, 0, 255), 5) | |
cv2.putText(cons_boxes_image, text, (int(box[0][0]), int(box[0][1])), cv2.FONT_HERSHEY_SIMPLEX, 1, (222, 0, 0), 1) | |
prev=0 | |
for box, text in zip(boxes, texts): | |
box_bottom_right_x = int(box[1][0]) | |
if(no_of_collisions>4): | |
break | |
# Draw the adjusted bounding box | |
if (num_l_x2 <= box_bottom_right_x <= num_r_x2): | |
# print("entered in the t/f column ") | |
if label_text(text)==True and text!='TRUE/FALSE': | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev=box[0][1] | |
prev_text=text | |
true_list.append(int(box[0][1])) | |
else: | |
if(abs(box[0][1]-prev)>200): #to avoid boxes in same row to overlap | |
print(text) | |
print(box) | |
true_list.append(int(box[0][1])) | |
prev=box[0][1] | |
prev_text=text | |
else: | |
print(f"collision happend with box:{prev} and text:{prev_text} solving on the basis of percent match boxes") | |
print("the current box specification are") | |
print(text) | |
print(box) | |
no_of_collisions+=1 | |
ans=percentMatch(prev_text,text) | |
if(ans==2): | |
if(label_text(prev_text)==False): | |
false_list.pop() | |
elif(label_text(prev_text)==True): | |
true_list.pop() | |
prev=box[0][1] | |
prev_text=text | |
true_list.append(int(prev)) | |
c+=1 | |
elif label_text(text)==False and text!='TRUE/FALSE': | |
if(c==0): | |
print("first t/f detection") | |
print(text) | |
print(box) | |
prev=box[0][1] | |
prev_text=text | |
false_list.append(int(box[0][1])) | |
else: | |
if(abs(box[0][1]-prev)>200): | |
print(text) | |
print(box) | |
false_list.append(int(box[0][1])) | |
prev=box[0][1] | |
prev_text=text | |
else: | |
print(f"collision happend with box:{prev} and text:{prev_text} solving on the basis of percent match boxes") | |
print("the current box specification are") | |
print(text) | |
print(box) | |
no_of_collisions+=1 | |
ans=percentMatch(prev_text,text) | |
if(ans==2): | |
if(label_text(prev_text)==False): | |
false_list.pop() | |
elif(label_text(prev_text)==True): | |
true_list.pop() | |
prev=box[0][1] | |
prev_text=text | |
false_list.append(int(prev)) | |
c+=1 | |
cv2.rectangle(cons_boxes_image,(int(box[0][0]),int(box[0][1])),(int(box[1][0]),int(box[1][1])),(0,0,255),5) | |
cv2.putText(cons_boxes_image,text,(int(box[0][0]),int(box[0][1])),cv2.FONT_HERSHEY_SIMPLEX,1,(222,0,0),1) | |
if(no_of_collisions<=4): | |
final_dict=assign_true_false_or_unknown(true_list,false_list,numbers_dict,total_questions) | |
else: | |
print("going with doctr less gap") | |
cons_boxes_image,final_dict=process_using_doctr_less_row_gap(boxes,texts,numbers_dict,num_l_x2,num_r_x2,image_path,total_questions) | |
# Create a unique output file name | |
output_file_name = f'final_tf_{base_name}' | |
output_file_path = os.path.join(output_folder, output_file_name) | |
# Save the processed image | |
cv2.imwrite(output_file_path, cons_boxes_image) | |
print("printing the number dict y_coordinate") | |
print(numbers_dict) | |
except NameError: | |
print("TRUE/FALSE not detected. Skipping this part of processing.") | |
print("going with paddleocr") | |
final_dict=process_using_paddleocr(image_path,output_folder,output_folder1,total_questions) | |
print("--------- Printing the final dict ------------") | |
print(final_dict) | |
df=pd.DataFrame(final_dict.items(),columns=['Q_No.','True/False']) | |
# predcsv_file_name = f'answers_{base_name}.csv' | |
# predcsv_file_path = os.path.join(output_folder, predcsv_file_name) | |
# df.to_csv(predcsv_file_path,index=False) | |
# print(f'DataFrame saved to {predcsv_file_path}') | |
# predictions_file_path='pred_output.csv' | |
# reading the answers and evaluting | |
marks=0 | |
w_ans=[] | |
m_ans=[] | |
for index, row in actualAns_df.iterrows(): | |
question_number = str(row.iloc[0]) # Accessing the first column by index | |
answer = row.iloc[1] # Accessing the second column by index | |
# print(answer) | |
if final_dict[question_number]==answer: | |
marks += 1 | |
elif final_dict[question_number] not in ("NULL", "UNASSIGNED"): | |
w_ans.append(question_number) | |
else: | |
m_ans.append(question_number) | |
print("Total Marks:", marks) | |
image_name = base_name #Replace this with the actual image name | |
marks_df = pd.DataFrame({"Filename": [image_name], "Marks": [marks]}) | |
# Append the marks DataFrame to the predictions file | |
# marks_df.to_csv(predictions_file_path, mode='a', header=False, index=False) | |
output_text = f"Marks: {marks} out of {total_questions}" | |
if w_ans: | |
output_text += f" and the following were wrong_answers: {w_ans}" | |
if m_ans and w_ans: | |
output_text += f" and missed_questions: {m_ans}" | |
if m_ans and len(w_ans)==0: | |
output_text += f" and the following were missed_answers: {m_ans}" | |
print(output_text) | |
return output_text | |
import gradio as gr | |
output_folder = "test_gradio/output" | |
output_folder1 = "test_gradio/detection" | |
# actual_ans_csv = "test_gradio/ModelAnswer.csv" | |
demo_image_paths = [ | |
"test_gradio/samples/1zHXQVK.jpg", | |
"test_gradio/samples/9X9qVWN.jpg", | |
"test_gradio/samples/LRccyJJ.jpg" | |
] | |
demo_csv_path = "test_gradio/answerKey.csv" | |
# Define the Gradio interface | |
demo = gr.Interface( | |
fn=lambda img_path, csv_path: process_and_save_image(img_path, csv_path, output_folder, output_folder1), | |
inputs=[gr.Image(type='filepath',label="Upload Image of your answer_sheet"), | |
gr.File(type='filepath',label="Upload the Answer Key in csv file")], | |
outputs=[gr.Textbox(label=f"Predicted Marks")], | |
title="AutoEval for True/False AnswerSheet", | |
examples=[ | |
[demo_image_paths[0], demo_csv_path], | |
[demo_image_paths[1], demo_csv_path], | |
[demo_image_paths[2], demo_csv_path] | |
] | |
) | |
# Launch the Gradio app | |
demo.launch() |