旋转不完整的盒子,使其垂直

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

http://img.mukewang.com/62d65cdc00017a9011550776.jpg

我目前正在研究计算 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)

并产生以下结果:

http://img2.mukewang.com/62d65cee000173c508610788.jpg

出错时:

http://img3.mukewang.com/62d65cfe0001217108720798.jpg

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



心有法竹
浏览 114回答 2
2回答

青春有我

这个想法是使用手臂本身的斑点并在其周围放置一个椭圆。然后,提取其主轴。我很快在Matlab中测试了这个想法——而不是 OpenCV。这是我所做的,您应该能够使用 OpenCV 的等效函数来实现类似的输出。首先,通过 Otsu 计算输入的阈值。然后对阈值添加一些偏差以找到更好的分割并使用该值对图像进行阈值处理。在伪代码中://the bias valuethreshBias = 0.4;//get the binary threshold via otsu: thresholdLevel = graythresh( grayInput, “otsu” );//add bias to the original valuethresholdLevel = 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 的最小区域的旋转矩形。

幕布斯6054654

您可以使用图像矩来计算旋转角度。使用 opencv矩函数,计算二阶中心矩以构造协方差矩阵,然后获得方向,如Image moment wiki 页面中所示。获得归一化中心矩,并从 opencv 。然后方向计算为nu20nu11nu02moments0.5 * arctan(2 * nu11/(nu20 - nu02))有关详细信息,请参阅给定的链接。您可以使用原始图像本身或预处理的图像来计算方向。看看哪一个可以为您提供更好的准确性并使用它。至于边界框,一旦旋转图像,假设您使用了预处理的图像,获取旋转图像的所有非零像素坐标并使用 opencv boundingRect计算它们的垂直边界框。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python