plot bboxes detected in transformed image in original image

55 views Asked by At

I am writing a code to automatically correct bubble sheets 4 choices. I want to plot bboxes around blacked rectangles(selected by students for the question) now I am using cv2.findContours and imutils.grab_contours and then four_point_transform to get biggest rectangle in my bubble sheet(its a custom bubble sheet which i have created my self. a big rectangle around circles will help us to get circles easier) everything looks good. but i want to save images after detecting and ploting bboxes around answers for every single question. i can plot around circles in transformed image, but how can i plot around circles in original one?

rectangles around answers in transformed image same rectangles in original image

i think i should use inverse of transform matrix and to get bboxes in original image. but i dont know is it possible or not, and how to do it if its.

this is my code if needed:

def find_answer(dst,):
    gray_dst = cv2.cvtColor(dst,cv2.COLOR_BGR2GRAY) 
    blurred_dst = cv2.GaussianBlur(gray_dst,(3,3),0)
    edged_dst = cv2.Canny(blurred_dst,75,200)
    black_threshold = np.sum(gray_dst[0:37,0:37])/(37*37)
    cnts = cv2.findContours(edged_dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    docCnt = None
    if len(cnts):
        cnts = sorted(cnts,key=cv2.contourArea,reverse=True)

    for c in cnts:
        peri = cv2.arcLength(c,True)
        approx = cv2.approxPolyDP(c,0.02*peri,True)
        if(len(approx))==4:
            docCnt = approx
            break
    paper =  four_point_transform(dst,docCnt.reshape(4,2))
    warped =  four_point_transform(gray_dst,docCnt.reshape(4,2)) 
    thresh = cv2.threshold(warped,0,255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)[1]
    cnts = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cnts = sorted(cnts,key=cv2.contourArea,reverse=True)
    answers = {}
    P=True
    for i in range(len(q)):

        w = q[i][0][2]
        h = q[i][0][3]
        area = w*h
        li = []
        for j  in range(len(q[i])):
            area =  q[i][j][2]*q[i][j][3]
            y1 = q[i][j][0]
            x1 = q[i][j][1]
            y2 = q[i][j][0] + q[i][j][2]
            x2 = q[i][j][1] +q[i][j][3]
            sum = np.sum(warped[x1:x2,y1:y2])
            #print(sum)
            #print(w,h)
            if sum/area <black_threshold:
                P = False
                print('i:',i,'j:',j,'sum is:',sum)
                print('thersh is:',area*188)
                li.extend([4-j])
        answers[i+1] = li
    return answers

four_point_transform:

def four_point_transform(image, pts):
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    # compute the width of the new image, which will be the
    # maximum distance between bottom-right and bottom-left
    # x-coordiates or the top-right and top-left x-coordinates
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    # compute the height of the new image, which will be the
    # maximum distance between the top-right and bottom-right
    # y-coordinates or the top-left and bottom-left y-coordinates
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    # now that we have the dimensions of the new image, construct
    # the set of destination points to obtain a "birds eye view",
    # (i.e. top-down view) of the image, again specifying points
    # in the top-left, top-right, bottom-right, and bottom-left
    # order
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype = "float32")
    # compute the perspective transform matrix and then apply it
    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
    # return the warped image
    return warped

order_points:

def order_points(pts):
    
    rect = np.zeros((4, 2), dtype = "float32")
    # the top-left point will have the smallest sum, whereas
    # the bottom-right point will have the largest sum
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    # now, compute the difference between the points, the
    # top-right point will have the smallest difference,
    # whereas the bottom-left will have the largest difference
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    # return the ordered coordinates
    return rect    

Thanks.

0

There are 0 answers