내 애플리케이션: 하고 나는 회전시키려면 이미지 (OpenCV 를 사용하여 및 파이썬)
! 이미지 회전
순간 나는 아래 코드를 개발한 이미지, 패딩, 나를 확증하노라 검은 테두리가 있는 회전시킵니다 입력 a 와 B - 제가 원하는 것은 가장 큰 가능한 지역으로 창 내의 오려내기로 회전되지 이미지. 내가 이 축 정렬되고 호출하십시오 경계 기입란.
그러나 이 같은 질문에 대한 답을 얻을 수 없습니다 (https://stackoverflow.com/questions/16255037/rotate-and-crop) 는 기본적으로 있는 것이다. 또한 사각형 이미지를생성하여 대해서만 답이 있는 것으로 알려졌다. 나의 이미지는 사각형.
코드 전달자로써 A:
import cv2
import numpy as np
def getTranslationMatrix2d(dx, dy):
"""
Returns a numpy affine transformation matrix for a 2D translation of
(dx, dy)
"""
return np.matrix([[1, 0, dx], [0, 1, dy], [0, 0, 1]])
def rotateImage(image, angle):
"""
Rotates the given image about it's centre
"""
image_size = (image.shape[1], image.shape[0])
image_center = tuple(np.array(image_size) / 2)
rot_mat = np.vstack([cv2.getRotationMatrix2D(image_center, angle, 1.0), [0, 0, 1]])
trans_mat = np.identity(3)
w2 = image_size[0] * 0.5
h2 = image_size[1] * 0.5
rot_mat_notranslate = np.matrix(rot_mat[0:2, 0:2])
tl = (np.array([-w2, h2]) * rot_mat_notranslate).A[0]
tr = (np.array([w2, h2]) * rot_mat_notranslate).A[0]
bl = (np.array([-w2, -h2]) * rot_mat_notranslate).A[0]
br = (np.array([w2, -h2]) * rot_mat_notranslate).A[0]
x_coords = [pt[0] for pt in [tl, tr, bl, br]]
x_pos = [x for x in x_coords if x > 0]
x_neg = [x for x in x_coords if x < 0]
y_coords = [pt[1] for pt in [tl, tr, bl, br]]
y_pos = [y for y in y_coords if y > 0]
y_neg = [y for y in y_coords if y < 0]
right_bound = max(x_pos)
left_bound = min(x_neg)
top_bound = max(y_pos)
bot_bound = min(y_neg)
new_w = int(abs(right_bound - left_bound))
new_h = int(abs(top_bound - bot_bound))
new_image_size = (new_w, new_h)
new_midx = new_w * 0.5
new_midy = new_h * 0.5
dx = int(new_midx - w2)
dy = int(new_midy - h2)
trans_mat = getTranslationMatrix2d(dx, dy)
affine_mat = (np.matrix(trans_mat) * np.matrix(rot_mat))[0:2, :]
result = cv2.warpAffine(image, affine_mat, new_image_size, flags=cv2.INTER_LINEAR)
return result
이 솔루션은 수학 견하여 구축상의 같습니다 / [이 솔루션을 통해 와 똑같이 질문] [1] 하지만 공식을 간편화된 특이성 피하고 있다. 이는 파이썬 코드를 largest_rotated_rect '에서' 와 동일한 인터페이스로, 다른 방법이 있지만, 더 큰 영역을 확증하노라 거의 모든 경우에 있어서 (프로세서입증된 항상 최적의):
def rotatedRectWithMaxArea(w, h, angle):
"""
Given a rectangle of size wxh that has been rotated by 'angle' (in
radians), computes the width and height of the largest possible
axis-aligned rectangle (maximal area) within the rotated rectangle.
"""
if w <= 0 or h <= 0:
return 0,0
width_is_longer = w >= h
side_long, side_short = (w,h) if width_is_longer else (h,w)
# since the solutions for angle, -angle and 180-angle are all the same,
# if suffices to look at the first quadrant and the absolute values of sin,cos:
sin_a, cos_a = abs(math.sin(angle)), abs(math.cos(angle))
if side_short <= 2.*sin_a*cos_a*side_long or abs(sin_a-cos_a) < 1e-10:
# half constrained case: two crop corners touch the longer side,
# the other two corners are on the mid-line parallel to the longer line
x = 0.5*side_short
wr,hr = (x/sin_a,x/cos_a) if width_is_longer else (x/cos_a,x/sin_a)
else:
# fully constrained case: crop touches all 4 sides
cos_2a = cos_a*cos_a - sin_a*sin_a
wr,hr = (w*cos_a - h*sin_a)/cos_2a, (h*cos_a - w*sin_a)/cos_2a
return wr,hr
이것은 다른 솔루션을 함께 작동할 비교:
>>> wl,hl = largest_rotated_rect(1500,500,math.radians(20))
>>> print (wl,hl),', area=',wl*hl
(828.2888697391496, 230.61639227890998) , area= 191016.990904
>>> wm,hm = rotatedRectWithMaxArea(1500,500,math.radians(20))
>>> print (wm,hm),', area=',wm*hm
(730.9511000407718, 266.044443118978) , area= 194465.478358
'A' 의 각도로 ' [0, pi/2 [' 경계 상자에 회전되지 이미지 (너비, 높이 '' w 'h') 는 이 치수들을:
'만약' ',' h_r w_r 오른길로 계산됩니까 최적이고 오려내었거나 이미지, 그 폭과 높이를 삽입에 경계 상자에서 다음과 같습니다.
의 수평 방향: '' (w_bb-w_r) /2
의 수직 방향: '' (h_bb-h_r) /2
Proof:*
둘 사이에 있는 영역은 사각형에는 정렬되고 보았으매 축의 최대 한 개의 매개변수입니다 평행선 최적화 문제, 예를 들어 'x' 로 이 그림. ! 애니메이션된 매개변수입니다
Let 's' 사이의 거리를 나타내는 두 개의 평행선 (it 발쿰치로 아웃하려면 포지셔닝합니다 회전되지 사각형에는 짧은 면). 그런 다음 면 'a', 'b' 의 인기가 있는 ',' x ',' s x 사각형에는 투명지에 상수입니다 제거율 관련어, 즉 x = a 보내거늘 & 알파;; 그리고 (s x) = b 코스는 &, 알파,:
그래서 이 지역은 ' 최대화합니다 고말은 최대화합니다' x ' (s x)'. &Quot 법칙 때문에, height". 직각으로 구부러진 대해 우리가 아는 삼각형 (s x) = 'x = *'. 따라서 최대 지역은 도달했음 dell. ', 즉 두 코너' E, G = x = s x s/2 평행선 사이에 있는 중간 라인:
이 솔루션은 이 최대 사각형에는 회전되지 사각형에는 맞추는 경우에만 유효합니다. 따라서 대각선 '예' 이상 'l' the other side of the 회전되지 사각형에는 않아야 합니다. 이후
예를 들어, DH = + = AF s/2 (간이침대 & 알파;; + 알파 탄 &;) = s / (, cos & sin &, 알파, 알파;) = s / 보내거늘 2*& 알파;;
우리는 찼음을 s &, le. , , 알파, 여기서 s 와 l 은 si 2& 짧고 긴 side of the 회전되지 사각형에는.
의 경우는 s >. , 2& si 알파. &prs. 'x' 의 인기가 더 있어야 합니다 (s/2 비해) 와 st 모든 모서리 부분에 대해 각각 사각형에는 회전되지 사각형에는. 이로 인해 방정식은요
, & co 알파. + 알파 (s x) 탄 &; = l
확증하노라 알파 (alpha, & co , , x = 보내거늘 &. , & si 알파;) / cos 2&, 알파. From a = x / 보내거늘 & 알파;; "b" = (s x) / cos & 알파;; 우리 위 수식에 사용되는 [1]: https://stackoverflow.com/questions/5789239/calculate-largest-rectangle-in-a-rotated-rectangle # 7519376
그래서, 많은 클레임됨 솔루션, 난 이제야 조사한 뒤 사용할 수 있는 방법을 발견했다. 정답은 [안드리] 에 의해 (https://stackoverflow.com/users/671973/andri) 및 [마그누스 호프] (https://stackoverflow.com/users/2971/magnus-hoff) 를 https://stackoverflow.com/questions/5789239/calculate-largest-rectangle-in-a-rotated-rectangle # 7519376.
아래 파이썬 코드를 largest_rotated_rect - 그리고 짧은 데모 '-' 방법을 포함하고 있다.
import math
import cv2
import numpy as np
def rotate_image(image, angle):
"""
Rotates an OpenCV 2 / NumPy image about it's centre by the given angle
(in degrees). The returned image will be large enough to hold the entire
new image, with a black background
"""
# Get the image size
# No that's not an error - NumPy stores image matricies backwards
image_size = (image.shape[1], image.shape[0])
image_center = tuple(np.array(image_size) / 2)
# Convert the OpenCV 3x2 rotation matrix to 3x3
rot_mat = np.vstack(
[cv2.getRotationMatrix2D(image_center, angle, 1.0), [0, 0, 1]]
)
rot_mat_notranslate = np.matrix(rot_mat[0:2, 0:2])
# Shorthand for below calcs
image_w2 = image_size[0] * 0.5
image_h2 = image_size[1] * 0.5
# Obtain the rotated coordinates of the image corners
rotated_coords = [
(np.array([-image_w2, image_h2]) * rot_mat_notranslate).A[0],
(np.array([ image_w2, image_h2]) * rot_mat_notranslate).A[0],
(np.array([-image_w2, -image_h2]) * rot_mat_notranslate).A[0],
(np.array([ image_w2, -image_h2]) * rot_mat_notranslate).A[0]
]
# Find the size of the new image
x_coords = [pt[0] for pt in rotated_coords]
x_pos = [x for x in x_coords if x > 0]
x_neg = [x for x in x_coords if x < 0]
y_coords = [pt[1] for pt in rotated_coords]
y_pos = [y for y in y_coords if y > 0]
y_neg = [y for y in y_coords if y < 0]
right_bound = max(x_pos)
left_bound = min(x_neg)
top_bound = max(y_pos)
bot_bound = min(y_neg)
new_w = int(abs(right_bound - left_bound))
new_h = int(abs(top_bound - bot_bound))
# We require a translation matrix to keep the image centred
trans_mat = np.matrix([
[1, 0, int(new_w * 0.5 - image_w2)],
[0, 1, int(new_h * 0.5 - image_h2)],
[0, 0, 1]
])
# Compute the tranform for the combined rotation and translation
affine_mat = (np.matrix(trans_mat) * np.matrix(rot_mat))[0:2, :]
# Apply the transform
result = cv2.warpAffine(
image,
affine_mat,
(new_w, new_h),
flags=cv2.INTER_LINEAR
)
return result
def largest_rotated_rect(w, h, angle):
"""
Given a rectangle of size wxh that has been rotated by 'angle' (in
radians), computes the width and height of the largest possible
axis-aligned rectangle within the rotated rectangle.
Original JS code by 'Andri' and Magnus Hoff from Stack Overflow
Converted to Python by Aaron Snoswell
"""
quadrant = int(math.floor(angle / (math.pi / 2))) & 3
sign_alpha = angle if ((quadrant & 1) == 0) else math.pi - angle
alpha = (sign_alpha % math.pi + math.pi) % math.pi
bb_w = w * math.cos(alpha) + h * math.sin(alpha)
bb_h = w * math.sin(alpha) + h * math.cos(alpha)
gamma = math.atan2(bb_w, bb_w) if (w < h) else math.atan2(bb_w, bb_w)
delta = math.pi - alpha - gamma
length = h if (w < h) else w
d = length * math.cos(alpha)
a = d * math.sin(alpha) / math.sin(delta)
y = a * math.cos(gamma)
x = y * math.tan(gamma)
return (
bb_w - 2 * x,
bb_h - 2 * y
)
def crop_around_center(image, width, height):
"""
Given a NumPy / OpenCV 2 image, crops it to the given width and height,
around it's centre point
"""
image_size = (image.shape[1], image.shape[0])
image_center = (int(image_size[0] * 0.5), int(image_size[1] * 0.5))
if(width > image_size[0]):
width = image_size[0]
if(height > image_size[1]):
height = image_size[1]
x1 = int(image_center[0] - width * 0.5)
x2 = int(image_center[0] + width * 0.5)
y1 = int(image_center[1] - height * 0.5)
y2 = int(image_center[1] + height * 0.5)
return image[y1:y2, x1:x2]
def demo():
"""
Demos the largest_rotated_rect function
"""
image = cv2.imread("lenna_rectangle.png")
image_height, image_width = image.shape[0:2]
cv2.imshow("Original Image", image)
print "Press [enter] to begin the demo"
print "Press [q] or Escape to quit"
key = cv2.waitKey(0)
if key == ord("q") or key == 27:
exit()
for i in np.arange(0, 360, 0.5):
image_orig = np.copy(image)
image_rotated = rotate_image(image, i)
image_rotated_cropped = crop_around_center(
image_rotated,
*largest_rotated_rect(
image_width,
image_height,
math.radians(i)
)
)
key = cv2.waitKey(2)
if(key == ord("q") or key == 27):
exit()
cv2.imshow("Original Image", image_orig)
cv2.imshow("Rotated Image", image_rotated)
cv2.imshow("Cropped Image", image_rotated_cropped)
print "Done"
if __name__ == "__main__":
demo()
배치하기만 하면 됩니다 [이 이미지] (http://i.stack.imgur.com/vWdWB.png) (오려내었거나 함께 있음을 알려주는 작동하잖아 정사각형이 아닌 이미지) 와 같은 디렉터리에 파일, 위의 실행하십시오 거잖나.
정말 대단한 일을 위한 축하! C++ 코드를 사용하여 라이브러리, 그래서 내가 하고 싶은 것을 제대로 켜졌습니까 OpenCV 로 변환 다음과 같다. 아마 다른 사람들은 이 외곽진입 도움이 될 수 있다.
#include <iostream>
#include <opencv.hpp>
#define PI 3.14159265359
using namespace std;
double degree_to_radian(double angle)
{
return angle * PI / 180;
}
cv::Mat rotate_image (cv::Mat image, double angle)
{
// Rotates an OpenCV 2 image about its centre by the given angle
// (in radians). The returned image will be large enough to hold the entire
// new image, with a black background
cv::Size image_size = cv::Size(image.rows, image.cols);
cv::Point image_center = cv::Point(image_size.height/2, image_size.width/2);
// Convert the OpenCV 3x2 matrix to 3x3
cv::Mat rot_mat = cv::getRotationMatrix2D(image_center, angle, 1.0);
double row[3] = {0.0, 0.0, 1.0};
cv::Mat new_row = cv::Mat(1, 3, rot_mat.type(), row);
rot_mat.push_back(new_row);
double slice_mat[2][2] = {
{rot_mat.col(0).at<double>(0), rot_mat.col(1).at<double>(0)},
{rot_mat.col(0).at<double>(1), rot_mat.col(1).at<double>(1)}
};
cv::Mat rot_mat_nontranslate = cv::Mat(2, 2, rot_mat.type(), slice_mat);
double image_w2 = image_size.width * 0.5;
double image_h2 = image_size.height * 0.5;
// Obtain the rotated coordinates of the image corners
std::vector<cv::Mat> rotated_coords;
double image_dim_d_1[2] = { -image_h2, image_w2 };
cv::Mat image_dim = cv::Mat(1, 2, rot_mat.type(), image_dim_d_1);
rotated_coords.push_back(cv::Mat(image_dim * rot_mat_nontranslate));
double image_dim_d_2[2] = { image_h2, image_w2 };
image_dim = cv::Mat(1, 2, rot_mat.type(), image_dim_d_2);
rotated_coords.push_back(cv::Mat(image_dim * rot_mat_nontranslate));
double image_dim_d_3[2] = { -image_h2, -image_w2 };
image_dim = cv::Mat(1, 2, rot_mat.type(), image_dim_d_3);
rotated_coords.push_back(cv::Mat(image_dim * rot_mat_nontranslate));
double image_dim_d_4[2] = { image_h2, -image_w2 };
image_dim = cv::Mat(1, 2, rot_mat.type(), image_dim_d_4);
rotated_coords.push_back(cv::Mat(image_dim * rot_mat_nontranslate));
// Find the size of the new image
vector<double> x_coords, x_pos, x_neg;
for (int i = 0; i < rotated_coords.size(); i++)
{
double pt = rotated_coords[i].col(0).at<double>(0);
x_coords.push_back(pt);
if (pt > 0)
x_pos.push_back(pt);
else
x_neg.push_back(pt);
}
vector<double> y_coords, y_pos, y_neg;
for (int i = 0; i < rotated_coords.size(); i++)
{
double pt = rotated_coords[i].col(1).at<double>(0);
y_coords.push_back(pt);
if (pt > 0)
y_pos.push_back(pt);
else
y_neg.push_back(pt);
}
double right_bound = *max_element(x_pos.begin(), x_pos.end());
double left_bound = *min_element(x_neg.begin(), x_neg.end());
double top_bound = *max_element(y_pos.begin(), y_pos.end());
double bottom_bound = *min_element(y_neg.begin(), y_neg.end());
int new_w = int(abs(right_bound - left_bound));
int new_h = int(abs(top_bound - bottom_bound));
// We require a translation matrix to keep the image centred
double trans_mat[3][3] = {
{1, 0, int(new_w * 0.5 - image_w2)},
{0, 1, int(new_h * 0.5 - image_h2)},
{0, 0, 1},
};
// Compute the transform for the combined rotation and translation
cv::Mat aux_affine_mat = (cv::Mat(3, 3, rot_mat.type(), trans_mat) * rot_mat);
cv::Mat affine_mat = cv::Mat(2, 3, rot_mat.type(), NULL);
affine_mat.push_back(aux_affine_mat.row(0));
affine_mat.push_back(aux_affine_mat.row(1));
// Apply the transform
cv::Mat output;
cv::warpAffine(image, output, affine_mat, cv::Size(new_h, new_w), cv::INTER_LINEAR);
return output;
}
cv::Size largest_rotated_rect(int h, int w, double angle)
{
// Given a rectangle of size wxh that has been rotated by 'angle' (in
// radians), computes the width and height of the largest possible
// axis-aligned rectangle within the rotated rectangle.
// Original JS code by 'Andri' and Magnus Hoff from Stack Overflow
// Converted to Python by Aaron Snoswell (https://stackoverflow.com/questions/16702966/rotate-image-and-crop-out-black-borders)
// Converted to C++ by Eliezer Bernart
int quadrant = int(floor(angle/(PI/2))) & 3;
double sign_alpha = ((quadrant & 1) == 0) ? angle : PI - angle;
double alpha = fmod((fmod(sign_alpha, PI) + PI), PI);
double bb_w = w * cos(alpha) + h * sin(alpha);
double bb_h = w * sin(alpha) + h * cos(alpha);
double gamma = w < h ? atan2(bb_w, bb_w) : atan2(bb_h, bb_h);
double delta = PI - alpha - gamma;
int length = w < h ? h : w;
double d = length * cos(alpha);
double a = d * sin(alpha) / sin(delta);
double y = a * cos(gamma);
double x = y * tan(gamma);
return cv::Size(bb_w - 2 * x, bb_h - 2 * y);
}
// for those interested in the actual optimum - contributed by coproc
#include <algorithm>
cv::Size really_largest_rotated_rect(int h, int w, double angle)
{
// Given a rectangle of size wxh that has been rotated by 'angle' (in
// radians), computes the width and height of the largest possible
// axis-aligned rectangle within the rotated rectangle.
if (w <= 0 || h <= 0)
return cv::Size(0,0);
bool width_is_longer = w >= h;
int side_long = w, side_short = h;
if (!width_is_longer)
std::swap(side_long, side_short);
// since the solutions for angle, -angle and pi-angle are all the same,
// it suffices to look at the first quadrant and the absolute values of sin,cos:
double sin_a = fabs(math.sin(angle)), cos_a = fabs(math.cos(angle));
double wr,hr;
if (side_short <= 2.*sin_a*cos_a*side_long)
{
// half constrained case: two crop corners touch the longer side,
// the other two corners are on the mid-line parallel to the longer line
x = 0.5*side_short;
wr = x/sin_a;
hr = x/cos_a;
if (!width_is_longer)
std::swap(wr,hr);
}
else
{
// fully constrained case: crop touches all 4 sides
double cos_2a = cos_a*cos_a - sin_a*sin_a;
wr = (w*cos_a - h*sin_a)/cos_2a;
hr = (h*cos_a - w*sin_a)/cos_2a;
}
return cv::Size(wr,hr);
}
cv::Mat crop_around_center(cv::Mat image, int height, int width)
{
// Given a OpenCV 2 image, crops it to the given width and height,
// around it's centre point
cv::Size image_size = cv::Size(image.rows, image.cols);
cv::Point image_center = cv::Point(int(image_size.height * 0.5), int(image_size.width * 0.5));
if (width > image_size.width)
width = image_size.width;
if (height > image_size.height)
height = image_size.height;
int x1 = int(image_center.x - width * 0.5);
int x2 = int(image_center.x + width * 0.5);
int y1 = int(image_center.y - height * 0.5);
int y2 = int(image_center.y + height * 0.5);
return image(cv::Rect(cv::Point(y1, x1), cv::Point(y2,x2)));
}
void demo(cv::Mat image)
{
// Demos the largest_rotated_rect function
int image_height = image.rows;
int image_width = image.cols;
for (float i = 0.0; i < 360.0; i+=0.5)
{
cv::Mat image_orig = image.clone();
cv::Mat image_rotated = rotate_image(image, i);
cv::Size largest_rect = largest_rotated_rect(image_height, image_width, degree_to_radian(i));
// for those who trust math (added by coproc):
cv::Size largest_rect2 = really_largest_rotated_rect(image_height, image_width, degree_to_radian(i));
cout << "area1 = " << largest_rect.height * largest_rect.width << endl;
cout << "area2 = " << largest_rect2.height * largest_rect2.width << endl;
cv::Mat image_rotated_cropped = crop_around_center(
image_rotated,
largest_rect.height,
largest_rect.width
);
cv::imshow("Original Image", image_orig);
cv::imshow("Rotated Image", image_rotated);
cv::imshow("Cropped image", image_rotated_cropped);
if (char(cv::waitKey(15)) == 'q')
break;
}
}
int main (int argc, char* argv[])
{
cv::Mat image = cv::imread(argv[1]);
if (image.empty())
{
cout << "> The input image was not found." << endl;
exit(EXIT_FAILURE);
}
cout << "Press [s] to begin or restart the demo" << endl;
cout << "Press [q] to quit" << endl;
while (true)
{
cv::imshow("Original Image", image);
char opt = char(cv::waitKey(0));
switch (opt) {
case 's':
demo(image);
break;
case 'q':
return EXIT_SUCCESS;
default:
break;
}
}
return EXIT_SUCCESS;
}
개인적으로 이 기능을 스노스웰 이 기능을 구현할 수 있으며, 이는 내가 필요한 TensorFlow 주셔서 감사합니다.
def _rotate_and_crop(image, output_height, output_width, rotation_degree, do_crop):
"""Rotate the given image with the given rotation degree and crop for the black edges if necessary
Args:
image: A `Tensor` representing an image of arbitrary size.
output_height: The height of the image after preprocessing.
output_width: The width of the image after preprocessing.
rotation_degree: The degree of rotation on the image.
do_crop: Do cropping if it is True.
Returns:
A rotated image.
"""
# Rotate the given image with the given rotation degree
if rotation_degree != 0:
image = tf.contrib.image.rotate(image, math.radians(rotation_degree), interpolation='BILINEAR')
# Center crop to ommit black noise on the edges
if do_crop == True:
lrr_width, lrr_height = _largest_rotated_rect(output_height, output_width, math.radians(rotation_degree))
resized_image = tf.image.central_crop(image, float(lrr_height)/output_height)
image = tf.image.resize_images(resized_image, [output_height, output_width], method=tf.image.ResizeMethod.BILINEAR, align_corners=False)
return image
def _largest_rotated_rect(w, h, angle):
"""
Given a rectangle of size wxh that has been rotated by 'angle' (in
radians), computes the width and height of the largest possible
axis-aligned rectangle within the rotated rectangle.
Original JS code by 'Andri' and Magnus Hoff from Stack Overflow
Converted to Python by Aaron Snoswell
Source: http://stackoverflow.com/questions/16702966/rotate-image-and-crop-out-black-borders
"""
quadrant = int(math.floor(angle / (math.pi / 2))) & 3
sign_alpha = angle if ((quadrant & 1) == 0) else math.pi - angle
alpha = (sign_alpha % math.pi + math.pi) % math.pi
bb_w = w * math.cos(alpha) + h * math.sin(alpha)
bb_h = w * math.sin(alpha) + h * math.cos(alpha)
gamma = math.atan2(bb_w, bb_w) if (w < h) else math.atan2(bb_w, bb_w)
delta = math.pi - alpha - gamma
length = h if (w < h) else w
d = length * math.cos(alpha)
a = d * math.sin(alpha) / math.sin(delta)
y = a * math.cos(gamma)
x = y * math.tan(gamma)
return (
bb_w - 2 * x,
bb_h - 2 * y
)
예를 들어, 시각화, 향후 구현에 필요한 경우 TensorFlow [이 리포지토리를] 에서 사용할 수 있습니다 (https://github.com/kobiso/Image-Rotation-and-Cropping-tensorflow). 다른 사람들은 이 도움이 될 수 있으면 좋겠다.
사용할 수 있는 작은 update 를 간략하게 뛰어난 이무티우스 라이브러리란.
def rotated_rect(w, h, angle):
"""
Given a rectangle of size wxh that has been rotated by 'angle' (in
radians), computes the width and height of the largest possible
axis-aligned rectangle within the rotated rectangle.
Original JS code by 'Andri' and Magnus Hoff from Stack Overflow
Converted to Python by Aaron Snoswell
"""
angle = math.radians(angle)
quadrant = int(math.floor(angle / (math.pi / 2))) & 3
sign_alpha = angle if ((quadrant & 1) == 0) else math.pi - angle
alpha = (sign_alpha % math.pi + math.pi) % math.pi
bb_w = w * math.cos(alpha) + h * math.sin(alpha)
bb_h = w * math.sin(alpha) + h * math.cos(alpha)
gamma = math.atan2(bb_w, bb_w) if (w < h) else math.atan2(bb_w, bb_w)
delta = math.pi - alpha - gamma
length = h if (w < h) else w
d = length * math.cos(alpha)
a = d * math.sin(alpha) / math.sin(delta)
y = a * math.cos(gamma)
x = y * math.tan(gamma)
return (bb_w - 2 * x, bb_h - 2 * y)
def crop(img, w, h):
x, y = int(img.shape[1] * .5), int(img.shape[0] * .5)
return img[
int(np.ceil(y - h * .5)) : int(np.floor(y + h * .5)),
int(np.ceil(x - w * .5)) : int(np.floor(x + h * .5))
]
def rotate(img, angle):
# rotate, crop and return original size
(h, w) = img.shape[:2]
img = imutils.rotate_bound(img, angle)
img = crop(img, *rotated_rect(w, h, angle))
img = cv2.resize(img,(w,h),interpolation=cv2.INTER_AREA)
return img
def rotate_bound(image, angle):
# CREDIT: https://www.pyimagesearch.com/2017/01/02/rotate-images-correctly-with-opencv-and-python/
(h, w) = image.shape[:2]
(cX, cY) = (w // 2, h // 2)
M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)
cos = np.abs(M[0, 0])
sin = np.abs(M[0, 1])
nW = int((h * sin) + (w * cos))
nH = int((h * cos) + (w * sin))
M[0, 2] += (nW / 2) - cX
M[1, 2] += (nH / 2) - cY
return cv2.warpAffine(image, M, (nW, nH))
def rotate_max_area(image, angle):
""" image: cv2 image matrix object
angle: in degree
"""
wr, hr = rotatedRectWithMaxArea(image.shape[1], image.shape[0],
math.radians(angle))
rotated = rotate_bound(image, angle)
h, w, _ = rotated.shape
y1 = h//2 - int(hr/2)
y2 = y1 + int(hr)
x1 = w//2 - int(wr/2)
x2 = x1 + int(wr)
return rotated[y1:y2, x1:x2]
27일 5월 2013년 코프로스 가장 선호하는 솔루션이므로 교정을 그들위에 주어진다. 코사 때 = 코스비 인피니티 결과 지난 2 선. Pardiso 추가하기만 ", 또는 코사 비유하 cosb". 위의 경우 선택기를.
추가: 모르면 비사양 회전되지 기존 nx 와 ny 회전되지 프레임 (또는 이미지) 을 찾을 수 있는 단지 그냥 이 들어 있는 상자 (나는한다 공백일 제거하여 = 이 흑백 테두리) 의 첫 번째 실행하십시오 고스란히 실현시키는 방식을 프로그램 및 파일 크기는 groupx nx 와 ny. 너무 작은 프레임 도왔으매 전송되었기 잘라냅니다 회전되지 경우 이미지 sanlight 붙여넣습니다 측면에 (into 팔각형 모양) 내가 처음 groupx x 와 y 를 전체 컨테인먼트를 확장명은 모함하는거. 그러나 이 또한 결과를 얻을 수 있는 사각형 ᄀ형강 약 45 도 작동하지 않습니다 유지하는 대신 비사양 회전되지 화면 비율. 이 때만 제대로 가져다줄래요 일상적인 최대 30 도.
여전히 큰 일상적인! 이 문제가 해결 내 잔소리를 천문학적 이미지 정렬.
덕분에 그의 코프록 위한 최적의 솔루션. 다음은 코드를 스위프트
// Given a rectangle of size.width x size.height that has been rotated by 'angle' (in
// radians), computes the width and height of the largest possible
// axis-aligned rectangle (maximal area) within the rotated rectangle.
func rotatedRectWithMaxArea(size: CGSize, angle: CGFloat) -> CGSize {
let w = size.width
let h = size.height
if(w <= 0 || h <= 0) {
return CGSize.zero
}
let widthIsLonger = w >= h
let (sideLong, sideShort) = widthIsLonger ? (w, h) : (w, h)
// since the solutions for angle, -angle and 180-angle are all the same,
// if suffices to look at the first quadrant and the absolute values of sin,cos:
let (sinA, cosA) = (sin(angle), cos(angle))
if(sideShort <= 2*sinA*cosA*sideLong || abs(sinA-cosA) < 1e-10) {
// half constrained case: two crop corners touch the longer side,
// the other two corners are on the mid-line parallel to the longer line
let x = 0.5*sideShort
let (wr, hr) = widthIsLonger ? (x/sinA, x/cosA) : (x/cosA, x/sinA)
return CGSize(width: wr, height: hr)
} else {
// fully constrained case: crop touches all 4 sides
let cos2A = cosA*cosA - sinA*sinA
let (wr, hr) = ((w*cosA - h*sinA)/cos2A, (h*cosA - w*sinA)/cos2A)
return CGSize(width: wr, height: hr)
}
}
아마 그것보다 더 간단 솔루션이므로 다음과 같습니다. "' 데프 crop_image (이미지, 각도): h, w = 앵거스샤피 tan_a = abs (np.턴 (ᄀ형강 np.피 / 180)) b = int (tan_a / (1 - tan_a 2) (h - w tan_a)) d = int (tan_a / (1 - tan_a 2) (w - h * tan_a)) 반품하십시오 이미지 [d - b - d, b w [h] "'
대신 높이와 너비입니다 회전되지 사각형에는 계산하는 것은 많은 고객들처럼 행한 com/go/downloads_kr 충분하나니) 의 이미지를 형성하는 검정색 삼각형 회전할 때.
이 문제를 쉽게 잘있게나 좁히어 가 사용하는 다른 모듈에서는 호출됨 필승 (도움됐네 그땅은 사용하지 않는 경우에만 함께 opencv)
아래 코드는 높여줍니까 모든 이미지 및 로이츠 똑같은 방식으로 너회가 won& # 39 검은 픽셀입니다 수 없다.
from PIL import Image
def array_to_img(x, scale=True):
x = x.transpose(1, 2, 0)
if scale:
x += max(-np.min(x), 0)
x /= np.max(x)
x *= 255
if x.shape[2] == 3:
return Image.fromarray(x.astype("uint8"), "RGB")
else:
return Image.fromarray(x[:,:,0].astype("uint8"), "L")
def img_to_array(img):
x = np.asarray(img, dtype='float32')
if len(x.shape)==3:
# RGB: height, width, channel -> channel, height, width
x = x.transpose(2, 0, 1)
else:
# grayscale: height, width -> channel, height, width
x = x.reshape((1, x.shape[0], x.shape[1]))
return x
if __name__ == "__main__":
# Calls a function to convert image to array
image_array = img_to_array(image_name)
# Calls the function to rotate the image by given angle
rotated_image = array_to_img(random_rotation(image_array, rotation_angle))
# give the location where you want to store the image
rotated_image_name=<location_of_the_image_>+'roarted_image.png'
# Saves the image in the mentioned location
rotated_image.save(rotated_image_name)