Python OpenCV Perspective transformation problems

Viewed 349

I am trying to make a perspective transformation with opencv. I want to extract screen from my e-book and align it.

1

First, I found a biggest contour and put it screenCnt2 variable. After that I extracted values to 2 lists:

x1_1 = [i[0] for j in screenCnt2 for i in j]
y1_1 = [i[1] for j in screenCnt2 for i in j]

Then, I calculated max_width and max_height of my subimage inside contours:

len_yr = np.sqrt((x1_1[1] - x1_1[0]) ** 2 + (y1_1[0] - y1_1[1])**2)
len_rb = np.sqrt((x1_1[1] - x1_1[2])**2 + (y1_1[2] - y1_1[1])**2)
len_bg = np.sqrt((x1_1[2] - x1_1[3])**2 + (y1_1[2] - y1_1[3])**2)
len_gy = np.sqrt((y1_1[3] - y1_1[0])**2 + (x1_1[0] - x1_1[3])**2)
print(len_yr, len_rb, len_bg, len_gy)
max_width = max(int(len_yr), int(len_bg))
max_height = max(int(len_gy), int(len_rb))

And finally apply perspective transforming

p1 = [i for i in zip(x1_1,y1_1)]
pts1 = np.float32(p1)
pts2 = np.float32([[0,0],[max_width - 1,0],[max_width - 1, max_height - 1],[0, max_height -1 ]])


M = cv2.getPerspectiveTransform(pts1,pts2)
dst2 = cv2.warpPerspective(seg_im3, M, (max_width, max_height))

x1_2 = [i[0] for i in pts2]
y1_2 = [i[1] for i in pts2]

plt.figure(figsize=(10, 10))
plt.subplot(121),plt.imshow(angle_im2[:, :, ::-1]),plt.title('Input')
plt.scatter(x1_1, y1_1, color = colors)
for x, y, color in zip(x1_1, y1_1, colors):
    plt.text(x, y, f'[{int(x)},{int(y)}]', color = color)
plt.subplot(122),plt.imshow(dst2[:, :, ::-1]),plt.title('Output')
plt.scatter(x1_2, y1_2, color = colors)
for x, y, color in zip(x1_2, y1_2, colors):
    plt.text(x, y, f'[{int(x)},{int(y)}]', color = color)
plt.show()

Final result: 2

I have no idea what I am doing wrong, because same code works fine with another image: 3

//EDIT

The red rectangle at first image is a biggest contour. To find it I use these 2 functions: adjust gamma to make image darker

def adjust_gamma(image, gamma=1.0):

   invGamma = 1.0 / gamma
   table = np.array([((i / 255.0) ** invGamma) * 255
      for i in np.arange(0, 256)]).astype("uint8")

   return cv2.LUT(image, table)

Then I found all contours and took the biggest:

def find_biggest_cnt(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, thrash = cv2.threshold(img_gray, 35 , 200, cv2.CHAIN_APPROX_NONE)
    cnts = cv2.findContours(thrash,cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    cnts = imutils.grab_contours(cnts)
    cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5]

    for c in cnts:
        peri = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.02 * peri, True)
        if len(approx) == 4:
            screenCnt = approx
            break
    return screenCnt

And result is: enter image description here

0 Answers
Related