本文介绍了从图像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.

  1. Kmeans 颜色量化. 我们加载图像,然后执行 Kmeans 颜色量化,将图像分割成指定的颜色簇.例如,使用 clusters=4,图像将被标记为四种颜色.

  1. 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中删除背景颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-31 05:43