Removing background color from image opencv python(从图像opencv python中删除背景颜色)
问题描述
我有许多样本图像,其背景颜色无法控制.其中一些具有黑色背景.其中一些具有白色背景.其中一些有绿色背景等.
I have many images of specimen which have uncontrollable background color. Some of them have black background. Some of them have white background. Some of them have green background, etc.
我想删除给定图像的这些背景颜色,其中图像中的对象只是一个样本.我尝试了这段代码,但它没有按我的预期工作.
I would like to remove these background color of a given image where the object in the image is just only one specimen. I try this code but it does not work as i expect.
def get_holes(image, thresh):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
im_bw = cv2.threshold(gray, thresh, 255, cv2.THRESH_BINARY)[1]
im_bw_inv = cv2.bitwise_not(im_bw)
_, contour, _ = cv2.findContours(im_bw_inv, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contour:
cv2.drawContours(im_bw_inv, [cnt], 0, 255, -1)
nt = cv2.bitwise_not(im_bw)
im_bw_inv = cv2.bitwise_or(im_bw_inv, nt)
return im_bw_inv
def remove_background(image, thresh, scale_factor=.25, kernel_range=range(1, 15), border=None):
border = border or kernel_range[-1]
holes = get_holes(image, thresh)
small = cv2.resize(holes, None, fx=scale_factor, fy=scale_factor)
bordered = cv2.copyMakeBorder(small, border, border, border, border, cv2.BORDER_CONSTANT)
for i in kernel_range:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (2*i+1, 2*i+1))
bordered = cv2.morphologyEx(bordered, cv2.MORPH_CLOSE, kernel)
unbordered = bordered[border: -border, border: -border]
mask = cv2.resize(unbordered, (image.shape[1], image.shape[0]))
fg = cv2.bitwise_and(image, image, mask=mask)
return fg
file = your_file_location
img = cv2.imread(file)
nb_img = dm.remove_background(img, 255)
这些是一些示例图像
我可以给你一些建议吗?
May i have your suggestions?
推荐答案
这是一个简单的方法,假设每个图像只有一个样本.
Here's a simple approach with the assumption that there is only one specimen per image.
Kmeans 颜色量化. 我们加载图像,然后执行 Kmeans 颜色量化,将图像分割成指定的颜色簇.例如,使用
clusters=4,图像将被标记为四种颜色.
Kmeans color quantization. We load the image then perform Kmeans color quantization to segment the image into a specified cluster of colors. For instance with
clusters=4, the image will be labeled into four colors.
获取二值图像.转换为灰度、高斯模糊、自适应阈值.
Obtain binary image. Convert to grayscale, Gaussian blur, adaptive threshold.
在遮罩上绘制最大的封闭圆. 查找轮廓,使用轮廓区域过滤对最大轮廓进行排序,然后使用 cv2.minEnclosureCircle.
Draw largest enclosing circle onto mask. Find contours, sort for largest contour using contour area filtering then draw the largest enclosing circle onto a mask using cv2.minEnclosingCircle.
按位与.由于我们已经隔离了要提取的所需部分,因此我们只需按位与掩码和输入图像
Bitwise-and. Since we have isolated the desired sections to extract, we simply bitwise-and the mask and input image
<小时>
输入图像-> Kmeans ->二值图像
Input image -> Kmeans -> Binary image
检测到最大包围圈->掩码->结果
Detected largest enclosing circle -> Mask -> Result
这是第二张图片的输出
输入图像-> Kmeans ->二值图像
Input image -> Kmeans -> Binary image
检测到最大包围圈->掩码->结果
Detected largest enclosing circle -> Mask -> Result
代码
import cv2
import numpy as np
# Kmeans color segmentation
def kmeans_color_quantization(image, clusters=8, rounds=1):
h, w = image.shape[:2]
samples = np.zeros([h*w,3], dtype=np.float32)
count = 0
for x in range(h):
for y in range(w):
samples[count] = image[x][y]
count += 1
compactness, labels, centers = cv2.kmeans(samples,
clusters,
None,
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10000, 0.0001),
rounds,
cv2.KMEANS_RANDOM_CENTERS)
centers = np.uint8(centers)
res = centers[labels.flatten()]
return res.reshape((image.shape))
# Load image and perform kmeans
image = cv2.imread('2.jpg')
original = image.copy()
kmeans = kmeans_color_quantization(image, clusters=4)
# Convert to grayscale, Gaussian blur, adaptive threshold
gray = cv2.cvtColor(kmeans, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,21,2)
# Draw largest enclosing circle onto a mask
mask = np.zeros(original.shape[:2], dtype=np.uint8)
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
((x, y), r) = cv2.minEnclosingCircle(c)
cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)
cv2.circle(mask, (int(x), int(y)), int(r), 255, -1)
break
# Bitwise-and for result
result = cv2.bitwise_and(original, original, mask=mask)
result[mask==0] = (255,255,255)
cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.imshow('mask', mask)
cv2.imshow('kmeans', kmeans)
cv2.imshow('image', image)
cv2.waitKey()
这篇关于从图像opencv python中删除背景颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从图像opencv python中删除背景颜色
基础教程推荐
- kivy 应用程序中的一个简单网页作为小部件 2022-01-01
- 究竟什么是“容器"?在蟒蛇?(以及所有的 python 容器类型是什么?) 2022-01-01
- matplotlib 设置 yaxis 标签大小 2022-01-01
- 在 Django Admin 中使用内联 OneToOneField 2022-01-01
- 比较两个文本文件以找出差异并将它们输出到新的文本文件 2022-01-01
- 在 Python 中将货币解析为数字 2022-01-01
- 对多索引数据帧的列进行排序 2022-01-01
- Python,确定字符串是否应转换为 Int 或 Float 2022-01-01
- Kivy 使用 opencv.调整图像大小 2022-01-01
- Python 中是否有任何支持将长字符串转储为块文字或折叠块的 yaml 库? 2022-01-01
