如何使二值图像中的所有背景变白
How can I make all background white in a binary image
在图像中,我希望只有黑色的肺而不是背景。背景 [图像的顶部黑色和底部黑色区域] 必须是白色而不是黑色。我怎样才能在 python 中做到这一点?。从原始灰度图像(“图像”)生成上图的代码是:
from skimage.filters import sobel
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
elevation_map = sobel(img)
markers = np.zeros_like(image)
markers[image < 70] = 1
markers[image > 254] = 2
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
假设我们有上面发布的 segmentation
图片,我们想用 while 填充周围的背景。
一个选项是迭代边界,并应用 floodFill
其中像素为黑色:
import cv2
import numpy as np
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
cv2.imshow('gray', gray)
cv2.waitKey()
cv2.destroyAllWindows()
其他选项是使用 MATLAB imfill(BW,'holes')
。
用白色填充中心黑色。
在原始图像中,用 while 填充原始图像和填充图像都是黑色的:
import cv2
import numpy as np
from skimage.morphology import reconstruction
def imfill(img):
#
# Use the matlab reference Soille, P., Morphological Image Analysis: Principles and Applications, Springer-Verlag, 1999, pp. 208-209.
# 6.3.7 Fillhole
# The holes of a binary image correspond to the set of its regional minima which
# are not connected to the image border. This definition holds for grey scale
# images. Hence, filling the holes of a grey scale image comes down to remove
# all minima which are not connected to the image border, or, equivalently,
# impose the set of minima which are connected to the image border. The
# marker image 1m used in the morphological reconstruction by erosion is set
# to the maximum image value except along its border where the values of the
# original image are kept:
seed = np.ones_like(img)*255
img[ : ,0] = 0
img[ : ,-1] = 0
img[ 0 ,:] = 0
img[ -1 ,:] = 0
seed[ : ,0] = 0
seed[ : ,-1] = 0
seed[ 0 ,:] = 0
seed[ -1 ,:] = 0
fill_img = reconstruction(seed, img, method='erosion')
return fill_img
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
fill_gray = imfill(gray)
# Fill with white where both gray and fill_gray are zeros
gray[(gray == 0) & (fill_gray == 0)] = 255;
cv2.imshow('gray', gray)
cv2.imshow('fill_gray', fill_gray)
cv2.waitKey()
cv2.destroyAllWindows()
我也考虑过使用 findContours 和层次结构来解决它,但它的编码有点多。
输出:
为了去除中心的黑点(如果需要),我们可以使用connectedComponentsWithStats
,并根据面积填充小“点”。
编辑:
将上述解决方案与您的代码合并的示例:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import skimage.io
import skimage.color
import skimage.filters
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.filters import sobel
import cv2
from skimage import data
image = cv2.imread('/content/drive/MyDrive/Covid_data/Training Set/covid/covid/ct_scan_100/22.jpg')
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Original Image')
# Image in grayscale
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Blurring the image [img]
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
#img = image
elevation_map = sobel(img)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(elevation_map, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('elevation_map')
# we find markers of the background and the coins based on the extreme parts of the histogram of grey values
markers = np.zeros_like(image)
# Choosing extreme parts of the histogram of grey values
markers[image < 70] = 1
markers[image > 254] = 2
#we use the watershed transform to fill regions of the elevation map starting from the markers determined above:
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
#gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
# Convert segmentation to uint8 image, where 255 is white and 0 is black (OpenCV style mask).
ret, gray = ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(gray, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('gray')
使用:ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
将 segmentation
中的所有白色像素替换为 255
,将所有黑色像素替换为 0
。
在图像中,我希望只有黑色的肺而不是背景。背景 [图像的顶部黑色和底部黑色区域] 必须是白色而不是黑色。我怎样才能在 python 中做到这一点?。从原始灰度图像(“图像”)生成上图的代码是:
from skimage.filters import sobel
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
elevation_map = sobel(img)
markers = np.zeros_like(image)
markers[image < 70] = 1
markers[image > 254] = 2
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
假设我们有上面发布的 segmentation
图片,我们想用 while 填充周围的背景。
一个选项是迭代边界,并应用 floodFill
其中像素为黑色:
import cv2
import numpy as np
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
cv2.imshow('gray', gray)
cv2.waitKey()
cv2.destroyAllWindows()
其他选项是使用 MATLAB imfill(BW,'holes')
。
用白色填充中心黑色。
在原始图像中,用 while 填充原始图像和填充图像都是黑色的:
import cv2
import numpy as np
from skimage.morphology import reconstruction
def imfill(img):
#
# Use the matlab reference Soille, P., Morphological Image Analysis: Principles and Applications, Springer-Verlag, 1999, pp. 208-209.
# 6.3.7 Fillhole
# The holes of a binary image correspond to the set of its regional minima which
# are not connected to the image border. This definition holds for grey scale
# images. Hence, filling the holes of a grey scale image comes down to remove
# all minima which are not connected to the image border, or, equivalently,
# impose the set of minima which are connected to the image border. The
# marker image 1m used in the morphological reconstruction by erosion is set
# to the maximum image value except along its border where the values of the
# original image are kept:
seed = np.ones_like(img)*255
img[ : ,0] = 0
img[ : ,-1] = 0
img[ 0 ,:] = 0
img[ -1 ,:] = 0
seed[ : ,0] = 0
seed[ : ,-1] = 0
seed[ 0 ,:] = 0
seed[ -1 ,:] = 0
fill_img = reconstruction(seed, img, method='erosion')
return fill_img
gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
fill_gray = imfill(gray)
# Fill with white where both gray and fill_gray are zeros
gray[(gray == 0) & (fill_gray == 0)] = 255;
cv2.imshow('gray', gray)
cv2.imshow('fill_gray', fill_gray)
cv2.waitKey()
cv2.destroyAllWindows()
我也考虑过使用 findContours 和层次结构来解决它,但它的编码有点多。
输出:
为了去除中心的黑点(如果需要),我们可以使用connectedComponentsWithStats
,并根据面积填充小“点”。
编辑:
将上述解决方案与您的代码合并的示例:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import skimage.io
import skimage.color
import skimage.filters
from skimage.io import imread
from skimage.color import rgb2gray
from skimage.filters import sobel
import cv2
from skimage import data
image = cv2.imread('/content/drive/MyDrive/Covid_data/Training Set/covid/covid/ct_scan_100/22.jpg')
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(image, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('Original Image')
# Image in grayscale
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Blurring the image [img]
img = cv2.GaussianBlur(image, (5, 5), 0)
img = cv2.erode(img, None, iterations=2)
img = cv2.dilate(img, None, iterations=2)
#img = image
elevation_map = sobel(img)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(elevation_map, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('elevation_map')
# we find markers of the background and the coins based on the extreme parts of the histogram of grey values
markers = np.zeros_like(image)
# Choosing extreme parts of the histogram of grey values
markers[image < 70] = 1
markers[image > 254] = 2
#we use the watershed transform to fill regions of the elevation map starting from the markers determined above:
segmentation = skimage.morphology.watershed(elevation_map, markers)
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(segmentation, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('segmentation')
#gray = cv2.imread('segmentation.png', cv2.IMREAD_GRAYSCALE) # Read image as grayscale
# Convert segmentation to uint8 image, where 255 is white and 0 is black (OpenCV style mask).
ret, gray = ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
for x in range(gray.shape[1]):
# Fill dark top pixels:
if gray[0, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, 0), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark bottom pixels:
if gray[-1, x] == 0:
cv2.floodFill(gray, None, seedPoint=(x, gray.shape[0]-1), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
for y in range(gray.shape[0]):
# Fill dark left side pixels:
if gray[y, 0] == 0:
cv2.floodFill(gray, None, seedPoint=(0, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
# Fill dark right side pixels:
if gray[y, -1] == 0:
cv2.floodFill(gray, None, seedPoint=(gray.shape[1]-1, y), newVal=255, loDiff=3, upDiff=3) # Fill the background with white color
fig, ax = plt.subplots(figsize=(7, 7))
ax.imshow(gray, cmap=plt.cm.gray, interpolation='nearest')
ax.axis('off')
ax.set_title('gray')
使用:ret, gray = cv2.threshold(segmentation.astype(np.uint8), 1, 255, cv2.THRESH_BINARY)
将 segmentation
中的所有白色像素替换为 255
,将所有黑色像素替换为 0
。