Hướng dẫn cv2 rotatedrect python - trăn xoay cv2

Tôi biết điều này đã được hỏi từ lâu, nhưng tôi muốn chia sẻ một cách tiếp cận khác như cách đề xuất bởi câu trả lời được chấp nhận, có lẽ điều này có thể hữu ích cho người khác (thực ra điều này đã được thực hiện trước đó trong C ++, nhưng có vẻ như Python vẫn thiếu của lớp xoay).

Ý tưởng là xác định một hình chữ nhật xoay từ một góc, kích thước (W và H) và điểm ban đầu. Điểm ban đầu này là góc trên cùng bên trái (góc trên cùng bên trái của cùng một hình chữ nhật kích thước không có góc xoay). Từ đây, bốn đỉnh có thể thu được, cho phép chúng ta vẽ hình chữ nhật xoay với bốn dòng.

class RRect:
  def __init__(self, p0, s, ang):
    self.p0 = (int(p0[0]),int(p0[1]))
    (self.W, self.H) = s
    self.ang = ang
    self.p1,self.p2,self.p3 = self.get_verts(p0,s[0],s[1],ang)
    self.verts = [self.p0,self.p1,self.p2,self.p3]

  def get_verts(self, p0, W, H, ang):
    sin = numpy.sin(ang/180*3.14159)
    cos = numpy.cos(ang/180*3.14159)
    P1 = (int(self.H*sin)+p0[0],int(self.H*cos)+p0[1])
    P2 = (int(self.W*cos)+P1[0],int(-self.W*sin)+P1[1])
    P3 = (int(self.W*cos)+p0[0],int(-self.W*sin)+p0[1])
    return [P1,P2,P3]

  def draw(self, image):
    print(self.verts)
    for i in range(len(self.verts)-1):
      cv2.line(image, (self.verts[i][0], self.verts[i][1]), (self.verts[i+1][0],self.verts[i+1][1]), (0,255,0), 2)
    cv2.line(image, (self.verts[3][0], self.verts[3][1]), (self.verts[0][0], self.verts[0][1]), (0,255,0), 2)

(W, H) = (30,60)
ang = 35 #degrees
P0 = (50,50)
rr = RRect(P0,(W,H),ang)
rr.draw(image)
cv2.imshow("Text Detection", image)
cv2.waitKey(200)

Tôi đoán, một cách tiếp cận tương tự có thể được sử dụng để xác định hình chữ nhật được xoay theo trung tâm của nó thay vì điểm ban đầu hàng đầu tương đối của nó, nhưng tôi chưa thử nó.

Trong blog trước, chúng tôi đã thảo luận về các khoảnh khắc hình ảnh và các tính năng đường viền khác nhau như khu vực, centroid, v.v ... có thể được trích xuất từ ​​chúng. Trong blog này, chúng tôi sẽ học cách vẽ một hình chữ nhật khu vực tối thiểu xung quanh khu vực quan tâm. Đây là một trong những nhiệm vụ phổ biến nhất được thực hiện khi làm việc với các đường viền. Vậy hãy bắt đầu.

Hình chữ nhật diện tích tối thiểu

Như rõ ràng từ tên, hình chữ nhật giới hạn được vẽ với diện tích tối thiểu. Bởi vì điều này, xoay vòng cũng được xem xét. Hình ảnh dưới đây cho thấy 2 hình chữ nhật màu xanh lá cây là hình chữ nhật giới hạn bình thường trong khi hình màu đỏ là hình chữ nhật diện tích tối thiểu. Xem cách hình chữ nhật màu đỏ được xoay.

OpenCV cung cấp một hàm cv2.minarearect () để tìm hình chữ nhật xoay diện tích tối thiểu. Điều này lấy làm đầu vào một tập điểm 2D và trả về cấu trúc Box2D chứa các chi tiết sau - (trung tâm (x, y), (chiều rộng, chiều cao), góc quay). Cú pháp được đưa ra dưới đây.

(tâm (x, y), (chiều rộng, chiều cao), góc quay) = cv2.minarect (điểm)center(x,y),(width,height),angle of rotation)=cv2.minAreaRect(points)

Nhưng để vẽ một hình chữ nhật, chúng ta cần 4 góc của hình chữ nhật. Vì vậy, để chuyển đổi cấu trúc Box2D thành 4 điểm góc, OpenCV cung cấp một hàm khác cv2.boxpoints (). Điều này lấy đầu vào cấu trúc Box2D và trả về 4 điểm góc. 4 điểm góc được đặt hàng theo chiều kim đồng hồ bắt đầu từ điểm với y cao nhất. Cú pháp được đưa ra dưới đây.

points=cv2.boxPoints(box)=cv2.boxPoints(box)

Trước khi vẽ hình chữ nhật, bạn cần chuyển đổi 4 góc thành loại số nguyên. Bạn có thể sử dụng NP.INT32 hoặc NP.INT64 (don lồng sử dụng np.int8 vì nó cho phép giá trị lên tới 127 và dẫn đến cắt ngắn sau đó). Đôi khi, bạn có thể thấy NP.INT0 được sử dụng, don lồng bị nhầm lẫn, điều này tương đương với NP.INT32 hoặc NP.INT64 Tùy thuộc vào kiến ​​trúc hệ thống của bạn. Mã đầy đủ được đưa ra dưới đây.

rect=cv2.minAreaRect(cnt)=cv2.minAreaRect(cnt)

box=cv2.boxPoints(rect)=cv2.boxPoints(rect)

box=np.int0(box)=np.int0(box)

Sau khi thu được 4 tọa độ, bạn có thể dễ dàng vẽ hình chữ nhật. Bây giờ, hãy để thảo luận về góc quay.

Góc quay

Như chúng ta đã thảo luận rằng 4 điểm góc được đặt hàng theo chiều kim đồng hồ bắt đầu từ điểm với Y cao nhất như hình dưới đây. Nếu 2 điểm có cùng Y cao nhất, thì điểm ngoài cùng bên phải là điểm bắt đầu. Các điểm được đánh số là 0,1,2,3 (0-khởi động, 3 kết thúc).

Hướng dẫn cv2 rotatedrect python - trăn xoay cv2

Vì vậy, góc xoay được đưa ra bởi OpenCV từ CV2.minArect () thực sự là góc giữa đường (nối vào điểm bắt đầu và điểm cuối) và ngang như hình dưới đây.

Hướng dẫn cv2 rotatedrect python - trăn xoay cv2

Do đó, giá trị góc luôn nằm giữa [-90,0). Tại sao? Bởi vì nếu đối tượng được xoay hơn 90 độ, thì cạnh tiếp theo được sử dụng để tính góc từ ngang. Và do đó góc tính toán luôn nằm giữa [-90,0). Xem hình ảnh dưới đây nơi đường màu xanh lá cây hiển thị đường nối vào điểm bắt đầu và điểm cuối được sử dụng để tính toán góc. Ngoài ra, xem cách bắt đầu và điểm cuối thay đổi khi đối tượng được xoay. Các điểm được đánh số là 0,1,2,3 (0-khởi động, 3 kết thúc).. Why? because if the object is rotated more than 90 degrees, then the next edge is used to calculate the angle from the horizontal. And thus the calculated angle always lies between [-90,0). See the below image where the green line shows the line joining the starting and endpoint that is used to calculate the angle. Also, see how the starting and endpoint change when the object is rotated. The points are numbered as 0,1,2,3 (0-starting, 3-end).

Hướng dẫn cv2 rotatedrect python - trăn xoay cv2

Góc thực tế là góc mà đối tượng được xoay và góc tính toán là góc được trả về bởi cv2.minarect ().Tôi hy vọng bạn hiểu làm thế nào góc được tính toán và tại sao nó nằm giữa [-90,0).

Trong blog tiếp theo, chúng tôi sẽ thảo luận về cách giải thích khu vực quan tâm bằng cách sử dụng góc thu được của cv2.minarect ().Hy vọng bạn thích đọc sách.

Nếu bạn có bất kỳ nghi ngờ/đề xuất nào xin vui lòng hỏi và tôi sẽ cố gắng hết sức để giúp đỡ hoặc cải thiện bản thân.Tạm biệt cho đến lần sau.