Python 乳腺x线最大轮廓的OpenCV分割

Python 乳腺x线最大轮廓的OpenCV分割,python,opencv,image-processing,image-segmentation,Python,Opencv,Image Processing,Image Segmentation,这可能有点太“一般”了,但如何执行灰度图像分割并保持最大轮廓?我试图从乳房X光片中去除背景噪音(即标签),但没有成功。以下是原始图像: 首先,我应用AGCWD算法(基于“使用加权分布的自适应伽马校正进行有效对比度增强”)以获得更好的图像像素对比度,如下所示: 之后,我尝试执行以下步骤: 使用OpenCV的KMeans聚类算法进行图像分割: enhanced_image_cpy = enhanced_image.copy() reshaped_image = np.float32(enhanc

这可能有点太“一般”了,但如何执行灰度图像分割并保持最大轮廓?我试图从乳房X光片中去除背景噪音(即标签),但没有成功。以下是原始图像:

首先,我应用AGCWD算法(基于“使用加权分布的自适应伽马校正进行有效对比度增强”)以获得更好的图像像素对比度,如下所示:

之后,我尝试执行以下步骤:

使用OpenCV的KMeans聚类算法进行图像分割:

enhanced_image_cpy = enhanced_image.copy()
reshaped_image = np.float32(enhanced_image_cpy.reshape(-1, 1))

number_of_clusters = 10
stop_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.1)

ret, labels, clusters = cv2.kmeans(reshaped_image, number_of_clusters, None, stop_criteria, 10, cv2.KMEANS_RANDOM_CENTERS)
clusters = np.uint8(clusters)
Canny边缘检测:

removed_cluster = 1

canny_image = np.copy(enhanced_image_cpy).reshape((-1, 1))
canny_image[labels.flatten() == removed_cluster] = [0]

canny_image = cv2.Canny(canny_image,100,200).reshape(enhanced_image_cpy.shape)
show_images([canny_image])
查找并绘制等高线:

initial_contours_image = np.copy(canny_image)
initial_contours_image_bgr = cv2.cvtColor(initial_contours_image, cv2.COLOR_GRAY2BGR)
_, thresh = cv2.threshold(initial_contours_image, 50, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(initial_contours_image_bgr, contours, -1, (255,0,0), cv2.CHAIN_APPROX_SIMPLE)
show_images([initial_contours_image_bgr])
以下是我绘制44004等高线后图像的外观:

我不知道如何才能得到一个大轮廓,而不是44004个小轮廓。任何关于如何修正我的方法的想法,或者任何关于使用替代方法摆脱右上角标签的想法


提前谢谢

在Python OpenCV中,有一种方法可以做到这一点

阅读图片

  • 阈值和反转,使边框为黑色
  • 按如下方式删除图像的边框(以便以后更容易获得相关轮廓):
  • 计算每列中非零像素的数量,并查找计数大于0的第一列和最后一列
  • 计算每行中非零像素的数量,并查找计数大于0的第一行和最后一行
  • 裁剪图像以删除边框
  • 收割thresh1并反转以制作thresh2
  • 从thresh2获取外部轮廓
  • 找到最大的轮廓并在黑色背景上绘制为白色填充作为遮罩
  • 使剪切图像中遮罩为黑色的所有像素为黑色
  • 保存结果-

输入:


阈值1图像:

裁剪图像:

阈值2图像:

遮罩图像:

结果:


您是否尝试过对图像进行阈值设置?低阈值应该是好的,因为背景大多为零加上一点噪声。
import cv2
import numpy as np

# read image
img = cv2.imread('xray3.png')

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold and invert
thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)[1]
thresh1 = 255 - thresh1

# remove borders
# count number of white pixels in columns as new 1D array
count_cols = np.count_nonzero(thresh1, axis=0)

# get first and last x coordinate where black
first_x = np.where(count_cols>0)[0][0]
last_x = np.where(count_cols>0)[0][-1]
print(first_x,last_x)

# count number of white pixels in rows as new 1D array
count_rows = np.count_nonzero(thresh1, axis=1)

# get first and last y coordinate where black
first_y = np.where(count_rows>0)[0][0]
last_y = np.where(count_rows>0)[0][-1]
print(first_y,last_y)

# crop image
crop = img[first_y:last_y+1, first_x:last_x+1]

# crop thresh1 and invert
thresh2 = thresh1[first_y:last_y+1, first_x:last_x+1]
thresh2 = 255 - thresh2

# get external contours and keep largest one
contours = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# make mask from contour
mask = np.zeros_like(thresh2 , dtype=np.uint8)
cv2.drawContours(mask, [big_contour], 0, 255, -1)

# make crop black everywhere except where largest contour is white in mask
result = crop.copy()
result[mask==0] = (0,0,0)

# write result to disk
cv2.imwrite("xray3_thresh1.jpg", thresh1)
cv2.imwrite("xray3_crop.jpg", crop)
cv2.imwrite("xray3_thresh2.jpg", thresh2)
cv2.imwrite("xray3_mask.jpg", mask)
cv2.imwrite("xray3_result.png", result)

# display it
cv2.imshow("thresh1", thresh1)
cv2.imshow("crop", crop)
cv2.imshow("thresh2", thresh2)
cv2.imshow("mask", mask)
cv2.imshow("result", result)
cv2.waitKey(0)