如何使用minAreaRect和C++将图像旋转180度?

3

我的图片:

这是一张图片描述

这是一张图片描述

这是一张图片描述

这是一张图片描述

要求:

这是一张图片描述

我不明白如何确定轴以使图像始终为水平状态。

算法:

  • 读取图像
  • 查找外部轮廓
  • 绘制轮廓
  • 使用外部轮廓检测 minArearect (边界框对我没有帮助)
  • 获取旋转矩阵并旋转图像
  • 从旋转后的图像中提取所需的补丁

我的代码:

//read the image
img = imread("90.jpeg")
cv::Mat contourOutput = img.clone();

// detect external contour(images will have noise, although example images doesn't have)

std::vector<std::vector<cv::Point> > contours;
cv::findContours(contourOutput, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

int largest_area = 0;
int largest_contour_index = 0;
for (size_t i = 0; i < contours.size(); i++) {
    double area = contourArea(contours[i]);

// copy the largest contour index
    if (area > largest_area) {
        largest_area = area;
        largest_contour_index = i;
}
}
//draw contours
drawContours(img, contours, largest_contour_index, Scalar(255, 0, 0),
             2);
// detect minimum area rect to get the angle and centre
cv::RotatedRect box = cv::minAreaRect(cv::Mat(contours[largest_contour_index]));
// take the box angle
double angle = box.angle;
if (angle < -45) {
    box.angle += 90;
}

angle = box.angle;
// create rotation matrix
cv::Mat rot_mat = cv::getRotationMatrix2D(box.center, angle, 1);

// Apply the transformation
cv::Mat rotated;
cv::warpAffine(img, rotated, rot_mat, img.size(), cv::INTER_CUBIC);
cv::Size box_size = box.size;

if (box.angle < -45.)
    std::swap(box_size.width, box_size.height);
// get the cropped image
cv::Mat cropped;
cv::getRectSubPix(rotated, box_size, box.center, cropped);

// Display the image
namedWindow("image2", WINDOW_NORMAL);
imshow("image2", cropped);
waitKey(0);

你需要角度还是旋转中心,或者有什么问题吗?请查看我在以下链接中的回答:https://dev59.com/JVsX5IYBdhLWcg3wFsTV#34285205 - Micka
我已经得到了角度,但是我不确定如何始终使它为180度(水平于x轴):( 因为我的图像角度不断变化。我是一个新手,已经卡了一天了!请帮帮我。 - user9324107
如果角度为10度,则将图像和框旋转170度。如果是33.3度,则旋转146.7度,依此类推。 - Micka
我已经让它这样工作了!但是我该如何推断何时交换box.width和box.height。我是否需要再次查找轮廓并绘制边界矩形来裁剪?这与使minAreaRect水平的相同问题有关。 - user9324107
1个回答

0

这个想法是使用minAreaRect计算旋转的边界框角度,然后使用getRotationMatrix2DwarpAffine对图像进行去倾斜处理。如果我们处理的是垂直图像,则最后一步是旋转90度。以下是旋转前(左)和旋转后(右)的结果以及旋转角度:

-39.999351501464844

38.52387619018555

1.6167902946472168

1.9749339818954468

我用Python实现了它,但是你可以将相同的方法适用于C++

代码

import cv2
import numpy as np

# Load image, grayscale, and Otsu's threshold
image = cv2.imread('4.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Compute rotated bounding box
coords = np.column_stack(np.where(thresh > 0))
angle = cv2.minAreaRect(coords)[-1]

# Determine rotation angle
if angle < -45:
    angle = -(90 + angle)
else:
    angle = -angle
print(angle)

# Rotate image to deskew
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)

# Vertical image so rotate to horizontal
h, w, _ = rotated.shape
if h > w:
    rotated = cv2.rotate(rotated, cv2.ROTATE_90_CLOCKWISE)

cv2.imshow('rotated', rotated)
cv2.imwrite('rotated.png', rotated)
cv2.waitKey()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接