乳房X光检查中最大轮廓的OpenCV分割 [英] OpenCV Segmentation of Largest contour in Breast Mammograms

查看:144
本文介绍了乳房X光检查中最大轮廓的OpenCV分割的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能有点一般".问题,但是如何执行GREYSCALE图像分割并保持最大轮廓呢?我正在尝试从乳房X光检查中消除背景噪音(即标签),但是我没有成功.这是原始图片:

This might be a bit too "general" question, but how do I perform GRAYSCALE image segmentation and keep the largest contour? I am trying to remove background noise (i.e. labels) from breast mammograms, but I am not successful. Here is the original image:

首先,我应用了AGCWD算法(基于论文使用具有权重分布的自适应伽玛校正的有效对比度增强"),以便获得更好的图像像素对比度,如下所示:

First, I applied AGCWD algorithm (based on paper "Efficient Contrast Enhancement Using Adaptive Gamma Correction With Weighting Distribution") in order to get better contrast of the image pixels, like so:

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

Afterwards, I tried executing following steps:

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

Image segmentation using OpenCV's KMeans clustering algorithm:

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边缘检测:

Canny Edge Detection:

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个轮廓后的图像外观:

Here is how image looks after I draw 44004 contours:

我不确定如何获得一个大轮廓,而不是44004个小轮廓.关于如何修正我的方法的任何想法,或者关于使用替代方法消除右上角标签的任何想法.

I am not sure how can I get one BIG contour, instead of 44004 small ones. Any ideas how to fix my approach, or possibly any ideas on using alternative approach to get rid of label in top right corner.

提前谢谢!

推荐答案

这是在Python OpenCV中实现此目的的一种方法

Here is one way to do that in Python OpenCV

阅读图像

  • 阈值并反转,以便边界为黑色
  • 按以下步骤删除图像的边框(以便以后更容易获得相关的轮廓):
  • 计算每列中非零像素的数量,并找到计数大于0的第一列和最后一列
  • 计算每行中非零像素的数量,并找到计数大于0的第一行和最后一行
  • 裁剪图像以去除边框
  • 种植thresh1并反转成thresh2
  • 从thresh2获取外部轮廓
  • 找到最大的轮廓并将其绘制为白色并填充在黑色背景上作为遮罩
  • 将蒙版为黑色的裁剪图像中的所有像素设为黑色
  • 保存结果-
  • Threshold and invert so the borders are black
  • Remove the borders of the image as follows (so as to make it easier to get the relevant contours later):
  • Count the number of non-zero pixels in each column and find the first and last column that have counts greater than 0
  • Count the number of non-zero pixels in each row and find the first and last row that have counts greater than 0
  • Crop the image to remove the borders
  • Crop thresh1 and invert to make thresh2
  • Get the external contours from thresh2
  • Find the largest contour and draw as white filled on a black background as a mask
  • Make all pixels in the cropped image black where the mask is black
  • Save the results -

输入:

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)

阈值1图片:

裁剪的图像:

阈值2图片:

蒙版图像:

结果:

这篇关于乳房X光检查中最大轮廓的OpenCV分割的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆