从图像opencv python中删除背景色 [英] Removing background color from image opencv python

查看:1349
本文介绍了从图像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)

这些是一些示例图片

请问您有什么建议吗?

推荐答案

这里假设每个图像只有一个标本,这是一种简单的方法.

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.

在蒙版上绘制最大的封闭圆.查找轮廓,使用轮廓区域过滤对最大轮廓进行排序,然后使用

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

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