import cv2 import numpy as np import utlis import gradio as gr def fun1(img): return img ######################################################################## def process_video(image_path): webCamFeed = True pathImage = "5.jpg" # cap = cv2.VideoCapture(image_path) # cap.set(10,160) heightImg = 700 widthImg = 700 questions=5 choices=5 ans= [1,2,0,2,4] ######################################################################## count=0 # while True: # if webCamFeed:success, img = cap.read() # else:img = cv2.imread(pathImage) img=cv2.imread(image_path) #read image from filepath img = cv2.resize(img, (widthImg, heightImg)) # RESIZE IMAGE imgFinal = img.copy() imgBlank = np.zeros((heightImg,widthImg, 3), np.uint8) # CREATE A BLANK IMAGE FOR TESTING DEBUGGING IF REQUIRED imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # CONVERT IMAGE TO GRAY SCALE imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1) # ADD GAUSSIAN BLUR imgCanny = cv2.Canny(imgBlur,10,70) # APPLY CANNY try: ## FIND ALL COUNTOURS imgContours = img.copy() # COPY IMAGE FOR DISPLAY PURPOSES imgBigContour = img.copy() # COPY IMAGE FOR DISPLAY PURPOSES contours, hierarchy = cv2.findContours(imgCanny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # FIND ALL CONTOURS cv2.drawContours(imgContours, contours, -1, (0, 255, 0), 10) # DRAW ALL DETECTED CONTOURS rectCon = utlis.rectContour(contours) # FILTER FOR RECTANGLE CONTOURS biggestPoints= utlis.getCornerPoints(rectCon[0]) # GET CORNER POINTS OF THE BIGGEST RECTANGLE gradePoints = utlis.getCornerPoints(rectCon[1]) # GET CORNER POINTS OF THE SECOND BIGGEST RECTANGLE if biggestPoints.size != 0 and gradePoints.size != 0: # BIGGEST RECTANGLE WARPING biggestPoints=utlis.reorder(biggestPoints) # REORDER FOR WARPING cv2.drawContours(imgBigContour, biggestPoints, -1, (0, 255, 0), 20) # DRAW THE BIGGEST CONTOUR pts1 = np.float32(biggestPoints) # PREPARE POINTS FOR WARP pts2 = np.float32([[0, 0],[widthImg, 0], [0, heightImg],[widthImg, heightImg]]) # PREPARE POINTS FOR WARP matrix = cv2.getPerspectiveTransform(pts1, pts2) # GET TRANSFORMATION MATRIX imgWarpColored = cv2.warpPerspective(img, matrix, (widthImg, heightImg)) # APPLY WARP PERSPECTIVE # SECOND BIGGEST RECTANGLE WARPING cv2.drawContours(imgBigContour, gradePoints, -1, (255, 0, 0), 20) # DRAW THE BIGGEST CONTOUR gradePoints = utlis.reorder(gradePoints) # REORDER FOR WARPING ptsG1 = np.float32(gradePoints) # PREPARE POINTS FOR WARP ptsG2 = np.float32([[0, 0], [325, 0], [0, 150], [325, 150]]) # PREPARE POINTS FOR WARP matrixG = cv2.getPerspectiveTransform(ptsG1, ptsG2)# GET TRANSFORMATION MATRIX imgGradeDisplay = cv2.warpPerspective(img, matrixG, (325, 150)) # APPLY WARP PERSPECTIVE # APPLY THRESHOLD imgWarpGray = cv2.cvtColor(imgWarpColored,cv2.COLOR_BGR2GRAY) # CONVERT TO GRAYSCALE imgThresh = cv2.threshold(imgWarpGray, 170, 255,cv2.THRESH_BINARY_INV )[1] # APPLY THRESHOLD AND INVERSE boxes = utlis.splitBoxes(imgThresh) # GET INDIVIDUAL BOXES # cv2.imshow("Split Test ", boxes[3]) countR=0 countC=0 myPixelVal = np.zeros((questions,choices)) # TO STORE THE NON ZERO VALUES OF EACH BOX for image in boxes: #cv2.imshow(str(countR)+str(countC),image) totalPixels = cv2.countNonZero(image) myPixelVal[countR][countC]= totalPixels countC += 1 if (countC==choices):countC=0;countR +=1 # FIND THE USER ANSWERS AND PUT THEM IN A LIST myIndex=[] for x in range (0,questions): arr = myPixelVal[x] myIndexVal = np.where(arr == np.amax(arr)) myIndex.append(myIndexVal[0][0]) #print("USER ANSWERS",myIndex) # COMPARE THE VALUES TO FIND THE CORRECT ANSWERS grading=[] for x in range(0,questions): if ans[x] == myIndex[x]: grading.append(1) else:grading.append(0) #print("GRADING",grading) score = (sum(grading)/questions)*100 # FINAL GRADE #print("SCORE",score) # DISPLAYING ANSWERS utlis.showAnswers(imgWarpColored,myIndex,grading,ans) # DRAW DETECTED ANSWERS utlis.drawGrid(imgWarpColored) # DRAW GRID imgRawDrawings = np.zeros_like(imgWarpColored) # NEW BLANK IMAGE WITH WARP IMAGE SIZE utlis.showAnswers(imgRawDrawings, myIndex, grading, ans) # DRAW ON NEW IMAGE invMatrix = cv2.getPerspectiveTransform(pts2, pts1) # INVERSE TRANSFORMATION MATRIX imgInvWarp = cv2.warpPerspective(imgRawDrawings, invMatrix, (widthImg, heightImg)) # INV IMAGE WARP # DISPLAY GRADE imgRawGrade = np.zeros_like(imgGradeDisplay,np.uint8) # NEW BLANK IMAGE WITH GRADE AREA SIZE cv2.putText(imgRawGrade,str(int(score))+"%",(70,100) ,cv2.FONT_HERSHEY_COMPLEX,3,(0,255,255)) # ADD THE GRADE TO NEW IMAGE invMatrixG = cv2.getPerspectiveTransform(ptsG2, ptsG1) # INVERSE TRANSFORMATION MATRIX imgInvGradeDisplay = cv2.warpPerspective(imgRawGrade, invMatrixG, (widthImg, heightImg)) # INV IMAGE WARP # SHOW ANSWERS AND GRADE ON FINAL IMAGE imgFinal = cv2.addWeighted(imgFinal, 1, imgInvWarp, 1,0) imgFinal = cv2.addWeighted(imgFinal, 1, imgInvGradeDisplay, 1,0) # IMAGE ARRAY FOR DISPLAY imageArray = ([img,imgGray,imgCanny,imgContours], [imgBigContour,imgThresh,imgWarpColored,imgFinal]) # cv2.imshow("Final Result", imgFinal) # yield imgFinal,None except: imageArray = ([img,imgGray,imgCanny,imgContours], [imgBlank, imgBlank, imgBlank, imgBlank]) # LABELS FOR DISPLAY lables = [["Original","Gray","Edges","Contours"], ["Biggest Contour","Threshold","Warpped","Final"]] stackedImage = utlis.stackImages(imageArray,0.5,lables) # cv2.imshow("Result",stackedImage) stackedImage = cv2.resize(stackedImage,(900,800)) yield imgFinal,stackedImage # SAVE IMAGE WHEN 's' key is pressed # cv2.imwrite("Scanned/myImage"+str(count)+".jpg",imgFinal) # cv2.rectangle(stackedImage, ((int(stackedImage.shape[1] / 2) - 230), int(stackedImage.shape[0] / 2) + 50), # (1100, 350), (0, 255, 0), cv2.FILLED) # cv2.putText(stackedImage, "Scan Saved", (int(stackedImage.shape[1] / 2) - 200, int(stackedImage.shape[0] / 2)), # cv2.FONT_HERSHEY_DUPLEX, 3, (0, 0, 255), 5, cv2.LINE_AA) # cv2.imshow('Result', stackedImage) # yield stackedImage # cv2.waitKey(300) count += 1 description_markdown = """ # OMR Grading tool made by Harpreet Singh ## Usage This tool expects an OMR sheet image consisting of 5 questions as input. Upon submission, it will process the image and provide an output with calculated obtained percentage displayed in Grade box available on image. ## Disclaimer Please note that this tool is for research purposes only and may not always be 100% accurate. Users are advised to exercise discretion and supervise the tool's usage accordingly. ## Developer Contact For further inquiries or permissions, you can reach out to the developer through the following social media accounts: - [LinkedIn](https://www.linkedin.com/in/harpreet-singh-4b1657251?utm_source=share&utm_campaign=share_via&utm_content=profile&utm_medium=android_app) - [GitHub](https://github.com/Harpreet-1313) """ app=gr.Interface( fn=process_video, # fn= fun1, inputs=gr.Image(type="filepath"), outputs=[gr.Image(),gr.Image()], examples=[["1.jpg"],["2.jpg"]], title="OMR Grading App", description= description_markdown, theme=gr.themes.Soft()) app.launch(auth=("username","password"),auth_message="Please Login")