Python:计算X射线中两块骨头之间的角度

时间:2018-04-10 00:49:54

标签: python image opencv graph hough-transform

我正在尝试编写一个脚本来计算给定X射线的两块骨头之间的角度。

样本X射线如下所示:

Sample x-ray

我试图计算每根骨骼的中线,基本上是骨骼两侧中点之后的一条线,然后比较两条中线之间的角度。

我尝试使用OpenCV来获取骨骼的轮廓,但它看起来不够准确并且获得了大量额外数据。我被困在如何移动下一步以及如何计算中线。我对图像处理很陌生,但对Python有经验。

使用OpenCV获得边缘结果:

enter image description here

OpenCV代码:

import cv2

# Load the image
img = cv2.imread("xray-3.jpg")

# Find the contours
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(img,60,200)
im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

hierarchy = hierarchy[0] # get the actual inner list of hierarchy descriptions

# For each contour, find the bounding rectangle and draw it
cv2.drawContours(img, contours, -1, (0,255,0), 3)

# Finally show the image
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

1 个答案:

答案 0 :(得分:1)

如果不作弊,我建议裁剪图像,尽量不要包含任何标签和比例,而不删除任何感兴趣的区域。

话虽如此,我认为如果对图像进行一些预处理,获取轮廓的方法将是可用的。一种可能做到这一点的算法是Difference of Gaussians(DoG)滤波器,它会使边缘更多。我稍微修改了this code,它将使用一些不同的 sigma k 值来计算DoG过滤器。

from skimage import io, feature, color, filters, img_as_float
from matplotlib import pyplot as plt

raw_img = io.imread('Pictures/bones.jpeg')
original_image = img_as_float(raw_img)
img = color.rgb2gray(original_image)

k = 1.6

plt.subplot(2,3,1)
plt.imshow(original_image)
plt.title('Original Image')

for idx,sigma in enumerate([4.0,8.0,16.0,32.0]):
    s1 = filters.gaussian(img,k*sigma)
    s2 = filters.gaussian(img,sigma)

    # multiply by sigma to get scale invariance
    dog = s1 - s2
    plt.subplot(2,3,idx+2)
    print dog.min(),dog.max()
    plt.imshow(dog,cmap='RdBu')
    plt.title('DoG with sigma=' + str(sigma) + ', k=' + str(k))

ax = plt.subplot(2,3,6)
blobs_dog = [(x[0],x[1],x[2]) for x in feature.blob_dog(img, min_sigma=4, max_sigma=32,threshold=0.5,overlap=1.0)]
# skimage has a bug in my version where only maxima were returned by the above
blobs_dog += [(x[0],x[1],x[2]) for x in feature.blob_dog(-img, min_sigma=4, max_sigma=32,threshold=0.5,overlap=1.0)]

#remove duplicates
blobs_dog = set(blobs_dog)

img_blobs = color.gray2rgb(img)
for blob in blobs_dog:
    y, x, r = blob
    c = plt.Circle((x, y), r, color='red', linewidth=2, fill=False)
    ax.add_patch(c)
plt.imshow(img_blobs)
plt.title('Detected DoG Maxima')

plt.show()

enter image description here

乍一看,似乎sigma = 8.0,k = 1.6可能是你最好的选择,因为这似乎最好地夸大了小腿的边缘,同时摆脱了它的噪音。特别是对象左侧(右图)腿。通过 k sigma 进行边缘检测,并让我知道你得到了什么:)

如果结果看起来很好,您应该能够在图像的每一行中检测到任一条腿的边缘之间获得中心点。然后找到适合任何一条腿的中间点的最佳线,你应该很高兴。你还需要将一条腿与另一条腿隔离开来,所以如果它没有作弊,可能会将图像从中间裁剪成两幅图像。