Reputation: 23
I have over 100 images that each of them is in different angle. I have written an basic python code to rotate each of the image one by one from any angle to zero degree ( I mean making them flat). The python code that I have attached is a simple code and unfortunately it doesn't automatically find the angle and it does not make it exact zero. Any time for any of the image I should find the angle and run the code for many time to make it zero (sometimes I am not able to make it exactly flat or what we celled zero degree). According to the images that I have attached, image1 is one of the sample image as an input and image_2 is the rotated image that I want to have at the end as an output. I would like to ask anyone that can help me to modify the current code or provide me with the new python code (which I prefer the new code)that I can make my images rotate from any angle to zero degree. please feel free to ask me for more explanation if you want.
my opencv-python code is:
import cv2
import numpy as np
img = cv2.imread('image1.tif')
num_rows, num_cols = img.shape[:2]
rotation_matrix = cv2.getRotationMatrix2D((num_cols/2, num_rows/2),69.4, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (num_cols, num_rows))
cv2.imshow('Rotation', img_rotation)
cv2.imwrite('image_2.tif',img_rotation)
cv2.waitKey()
Note: input and output images deleted.
Upvotes: 2
Views: 926
Reputation: 13087
it's definitely not the most robust method, but perhaps an option would be to:
alpha = math.atan2(x1-x0,y1-y0)
I downloaded your figure (it was converted to png on imgur) and tested the procedure with:
#!/usr/bin/env python
import cv2
import math
import numpy as np
img = cv2.imread('test.png')
H, W = img.shape[:2]
x0,y0 = None,None
x1,y1 = None,None
#scan all rows starting with the first
for i in range(0, H):
row = img[i].sum(axis=1)
s = np.sum(row)
if s:
#if there is at least one non-black pixel, mark
#its position
x0 = np.max(np.where(row>0))
y0 = i
break
#scan all columns starting with the right-most one
for j in range(W-1,-1,-1):
col = img[:,j,:].sum(axis=1)
s = np.sum(col)
if s:
#mark the position of the first non-black pixel
x1 = j
y1 = np.min(np.where(col>0))
break
dx = x1 - x0
dy = y1 - y0
alpha = math.atan2(dx, dy) / math.pi * 180
rotation_matrix = cv2.getRotationMatrix2D((W/2, H/2), -alpha, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (W, H))
cv2.imwrite('image_2.tif',img_rotation)
EDIT:
The previous method can be inaccurate in case the "corner" pixel is black as well so that the calculated angle is then biased. Slightly more accurate approach could be as follows:
The implementation:
#!/usr/bin/env python
import cv2
import math
import numpy as np
img = cv2.imread('test.png')
H, W = img.shape[:2]
data = []
for j in range(0, W):
col = img[:,j,:].sum(axis=1)
s = np.sum(col)
if not s:
continue
for i in range(0, H):
if col[i] > 0:
data.append((j, i))
break
y_min, min_pos = None, None
for idx, (x, y) in enumerate(data):
if y_min is None or y < y_min:
y_min = y
min_pos = idx
N = len(data)
if min_pos > N - min_pos:
data = data[:min_pos]
else:
data = data[min_pos:]
data = np.asarray(data).T
coeffs = np.polyfit(data[0], data[1], 1)
alpha = math.atan(coeffs[0]) / math.pi * 180
print(alpha)
rotation_matrix = cv2.getRotationMatrix2D((W/2, H/2), alpha, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (W, H))
cv2.imwrite('image_2.tif',img_rotation)
Upvotes: 1
Reputation: 1
another way to find the angle is (asuming that the image is over a black background):
Find the parameters of the ellipse that fit the contour
import cv2
import numpy as np
image = cv2.imread("DlYEa.png")
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
num_rows, num_cols = image.shape[:2]
_, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
img, contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]
(x, y), (Ma, ma), angle = cv2.fitEllipse(cnt)
angle = int(angle - 90)
rotation_matrix = cv2.getRotationMatrix2D((num_cols/2, num_rows/2), angle, 1)
img_rotation = cv2.warpAffine(image, rotation_matrix, (num_cols, num_rows))
cv2.imshow("rotation", img_rotation)
cv2.waitKey()
cv2.destroyAllWindows()
Upvotes: 0