Home > Back-end >  image rectification on pressure gauge, rotate it vertically
image rectification on pressure gauge, rotate it vertically

Time:10-26

im currently trying to implement a paper of reading pressure gauges. There is a step where i dont know what to do. It says: "The display contour is then rotated to vertically align the long axis of the ellipse and inscribed in a rectangle used to crop the gauge image." So im not sure how i can rotate this image vertically, for better understanding i will show you a example what the current image is and what it needs to be.

enter image description here

Im currently at step C and need to get the image in position of step D. The text detection in the example is currently not important.

At the moment i have the correct contours and ellipse for the display.

(cnts, boundingBoxes) = sort_contours(cnts)
#find correct contours and fitellipse
if len(cnts) != 0:
  for i in range(len(cnts)):
    if len(cnts[i]) >= 5: #if contours has more than 5 points
      # cv2.drawContours(image,cnts[0],-1,(150,10,255),3)
      ellipse = cv2.fitEllipse(cnts[i])
      finalElps.append(ellipse) #(centx,centy), (width,height), angle

for i in range(len(finalElps)):
  centx = finalElps[i][0][0]
  centy = finalElps[i][0][1]
  eWidth = finalElps[i][1][0]
  eHeight = finalElps[i][1][1]
  sfRes = Sf(eWidth, eHeight)
  cfRes = Cf(centx, imgCenterX, centy, imgCenterY)
  afRes = Af(eWidth,eHeight,imgWidth,imgHeight)
  print("SF: "   str(sfRes)   "| "   "CF: "   str(cfRes)   "| Af: "   str(afRes))
  if(sfRes < 0.4 and cfRes < 6 and afRes < 0.9):
    print(finalElps[i])
    cv2.ellipse(image, finalElps[i], (255,0,0), 2)
    plt.imshow(image)

sfRes, cfRes and afRes are just calculations to find the right ellipse.

What should be my next step to reach the vertical rotation? I think the correct name for it is "image rectification" but im not 100% sure about it

CodePudding user response:

Here is how to get the image D from the image C:

  1. Find the binary mask

enter image description here

  1. Find an ellipse (center, width, height, angle)

enter image description here

  1. Find 4 points on opposite sides of the ellipse

enter image description here

  1. Use these 4 points to get perspective transform that can be used to warp the rotated gauge image to rectangular image. The final result:

enter image description here

Code:

import cv2
import numpy as np


image = cv2.imread("gauge.png")

# find the parameters of the ellipse
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
mask = cv2.threshold(gray, 10, 255, cv2.THRESH_BINARY)[1]
points = np.stack(np.nonzero(mask.T)).T
hull = cv2.convexHull(points)
(cx, cy), (width, height), angle = cv2.fitEllipse(hull)

# for visualization
# cv2.ellipse(image, (int(cx), int(cy)), (int(width/2), int(height/2)), angle, 0, 360, (0, 0, 255), 2)

# find the points on the opposite sides of the ellipse
# define rectangular homogenuous coordinates and rotate them using a rotation matrix
mat = cv2.getRotationMatrix2D((cx, cy), -angle, 1)
mat = np.vstack((mat, [0, 0, 1]))
coords = np.array(
    [
        [cx   width // 2, cy, 1],
        [cx - width // 2, cy, 1],
        [cx, cy   height // 2, 1],
        [cx, cy - height // 2, 1],
    ]
)
points = (mat @ coords.T)[:2].T  # drop the homogenuos part

# for visualization
# for px, py in points.astype(int)[:2]:
#     cv2.circle(image, (px, py), 10, (0, 0, 255), -1)
# for px, py in points.astype(int)[2:]:
#     cv2.circle(image, (px, py), 10, (255, 0, 0), -1)

# define points on the target image to which the ellipse points should be mapped
size = 300
target = np.float32(
    [
        [size, size // 2],
        [0, size // 2],
        [size // 2, size],
        [size // 2, 0],
    ]
)
mat = cv2.getPerspectiveTransform(points.astype(np.float32), target)
rect_image = cv2.warpPerspective(image, mat, (size, size))

cv2.imwrite("rect_gauge.png", rect_image)
  • Related