【问题标题】:Rotate incomplete box so it is vertical旋转不完整的盒子,使其垂直
【发布时间】:2020-02-05 19:44:15
【问题描述】:

我有一个 X 射线图像数据集,我试图通过旋转图像来清理它,使手臂垂直并裁剪任何多余空间的图像。以下是数据集中的一些示例:

我目前正在研究计算 X 射线角度并以此为基础旋转图像的最佳方法。

我目前的方法是使用霍夫变换检测扫描所在矩形边的线,并据此旋转图像。

我尝试在精明边缘检测器的输出上运行霍夫变换,但这对于矩形边缘像第一张图像一样模糊的图像效果不佳。

我不能使用 cv 的框检测,因为有时扫描周围的矩形有边缘超出屏幕。

所以我目前使用自适应阈值来找到框的边缘,然后对其进行中值滤波并尝试在其中找到最长的线,但有时错误的线是最长的,并且图像被旋转完全错误。

由于某些扫描具有不同的亮度,因此使用了自适应阈值。

我目前的实现是:

def get_lines(img):
  #threshold
  thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 15, 4.75)
  median = cv2.medianBlur(thresh, 3)
  # detect lines
  lines = cv2.HoughLines(median, 1, np.pi/180, 175)
  return sorted(lines, key=lambda x: x[0][0], reverse=True)

def rotate(image, angle):
  (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 fix_rotation(input):
  lines = get_lines(input)
  rho, theta = lines[0][0]
  return rotate_bound(input, theta*180/np.pi)

并产生以下结果:

出错时:

我想知道是否有任何更好的技术可以使用以提高性能,以及在图像旋转后裁剪图像的最佳方法是什么?

【问题讨论】:

标签: python opencv image-processing


【解决方案1】:

这个想法是使用手臂本身的斑点并在其周围放置一个椭圆。然后,提取其主轴。我很快在 Matlab 中测试了这个想法——而不是 OpenCV。这是我做的,你应该可以使用OpenCV的等效函数来实现类似的输出。

首先,通过 Otsu 计算输入的阈值。然后对阈值添加一些偏差以找到更好的分割并使用该值对图像进行阈值处理。

在伪代码中:

//the bias value
threshBias = 0.4;

//get the binary threshold via otsu: 
thresholdLevel = graythresh( grayInput, “otsu” );

//add bias to the original value
thresholdLevel = thresholdLevel - threshSensitivity * thresholdLevel;

//get the fixed binary image: 
thresholdLevel = imbinarize( grayInput, thresholdLevel );

经过小斑点过滤后,输出如下:

现在,获取轮廓/斑点并为每个轮廓拟合一个椭圆。在此处查看 OpenCV 示例:https://docs.opencv.org/3.4.9/de/d62/tutorial_bounding_rotated_ellipses.html

你会得到两个省略号:

我们正在寻找最大的椭圆,即面积最大、长轴和短轴最大的椭圆。我使用每个椭圆的宽度和高度来过滤结果。然后将目标椭圆着色为绿色。最后,我得到了目标椭圆的长轴,这里用黄色着色:

现在,要在 OpenCV 中实现这些想法,您有以下选择:

  • 使用fitEllipse 查找省略号。这个的返回值 函数是一个RotatedRect 对象。这里存储的数据是 椭圆的顶点。

  • 您可以尝试使用minAreaRect,而不是拟合椭圆, 找到一个包含一个 blob 的最小区域的旋转矩形。

【讨论】:

    【解决方案2】:

    您可以使用图像矩来计算旋转角度。 使用 opencv moments 函数,计算二阶中心矩以构造协方差矩阵,然后获得 Image moment wiki 页面中 here 所示的方向。 从 opencv moments 获取归一化中心矩 nu20nu11nu02。然后方向计算为

    0.5 * arctan(2 * nu11/(nu20 - nu02))

    详情请参考给定的链接。

    您可以使用原始图像本身或经过预处理的图像来计算方向。看看哪一个可以提供更好的准确性并使用它。

    至于边界框,一旦你旋转图像,假设你使用了预处理的,得到旋转图像的所有非零像素坐标,并使用 opencv boundingRect 计算它们的垂直边界框。

    【讨论】:

    • 感谢回复,能否详细说明如何利用矩来查找图片的旋转?
    • @user6817585 请按照我上面给出的方法进行操作。在“核心时刻”部分下给出了一个示例,清楚地说明了如何执行此操作。
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 2017-12-07
    相关资源
    最近更新 更多