1

I have this black and white image, which I would like to transform into a new image where the 4 corner balls will form a perfectly upright rectangle and keep all relative distances among all objects of the original image.

I believe that a sort of rotation would accomplish what I am wanting, but, being a novice with OpenCV, I do not know how to do that. As far as I have learned, one can rotate an image, but what I am wanting is not to rotate the entire image but only the above described rectangle of balls (and all objects inside that rectangle).

Any suggestions would be very much appreciated.

Thanks in advanceMy image.

PaulS
  • 21,159
  • 2
  • 9
  • 26
  • "Not the entire image": what difference would it make, there's nothing around the rectangle ? –  Jun 27 '20 at 16:24
  • Thanks, Yves. True, but the whole image will become rotated and I want it upright. Perhaps, there a trick to do that. – PaulS Jun 27 '20 at 16:58
  • 1
    No, all images in the world are upright ! If you rotate the content, parts are clipped and parts are filled with something. –  Jun 27 '20 at 17:45
  • Got it, Yves! Meanwhile, I was able to rotate my image with ```cv2.getRotationMatrix2D``` and ```cv2.warpAffine```. The problem now is to find the exact rotation angle that makes the rectangle of balls (mentioned in my question) perfectly upright, with no inclination. – PaulS Jun 27 '20 at 19:54
  • 1
    You need to find the centroids of the white disks or black rings. –  Jun 28 '20 at 14:26
  • @PaulSmith Please [edit](https://stackoverflow.com/posts/62611014/edit) the post to include your own effort into solving this problem. The latter preferably in code, this is called a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – Bilal Jun 28 '20 at 19:52
  • It seems like you should use template matching to find the corner circles. [This answer](https://stackoverflow.com/a/58514954/9705687) has a scheme for finding multiple templates. – bfris Jul 01 '20 at 19:42

1 Answers1

0

Thanks for all comments, which put me on the right track.

I have solved my own problem, using the following Python code:

import cv2
import numpy as np

img = cv2.imread('x.jpg', -1)
h, w = img.shape

img2 = img[:400, :400]

iIndex = np.where(img2 == 0)

xmed1 = np.mean(iIndex[0])
ymed1 = np.mean(iIndex[1])

img2 = img[:400, w-400:]

iIndex = np.where(img2 == 0)

xmed2 = np.mean(iIndex[0])
ymed2 = np.mean(iIndex[1]) + w - 100

angle = np.arctan((xmed2-xmed1)/(ymed2-ymed1))
angle = np.degrees(angle)

m = cv2.getRotationMatrix2D((xmed1,ymed1), angle, 1)
imgR = cv2.warpAffine(img, m, (w, h))

imgR[:, :100] = 255
imgR[:, w - 100:] = 255
imgR[-100:, :] = 255
imgR[:100, :] = 255

cv2.namedWindow('rotated', cv2.WINDOW_KEEPRATIO)
cv2.imshow('rotated', imgR)
cv2.resizeWindow('rotated', 1000, 1000)


cv2.waitKey(0)
cv2.destroyAllWindows()
PaulS
  • 21,159
  • 2
  • 9
  • 26