問(wèn)題描述
我有許多樣本圖像,其背景顏色無(wú)法控制.其中一些具有黑色背景.其中一些具有白色背景.其中一些有綠色背景等.
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.
我想刪除給定圖像的這些背景顏色,其中圖像中的對(duì)象只是一個(gè)樣本.我嘗試了這段代碼,但它沒(méi)有按我的預(yù)期工作.
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?
推薦答案
這是一個(gè)簡(jiǎn)單的方法,假設(shè)每個(gè)圖像只有一個(gè)樣本.
Here's a simple approach with the assumption that there is only one specimen per image.
Kmeans 顏色量化. 我們加載圖像,然后執(zhí)行 Kmeans 顏色量化,將圖像分割成指定的顏色簇.例如,使用
clusters=4
,圖像將被標(biāo)記為四種顏色.
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.
獲取二值圖像.轉(zhuǎn)換為灰度、高斯模糊、自適應(yīng)閾值.
Obtain binary image. Convert to grayscale, Gaussian blur, adaptive threshold.
在遮罩上繪制最大的封閉圓. 查找輪廓,使用輪廓區(qū)域過(guò)濾對(duì)最大輪廓進(jìn)行排序,然后使用 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
.
按位與.由于我們已經(jīng)隔離了要提取的所需部分,因此我們只需按位與掩碼和輸入圖像
Bitwise-and. Since we have isolated the desired sections to extract, we simply bitwise-and the mask and input image
<小時(shí)>
輸入圖像->
Kmeans ->
二值圖像
Input image ->
Kmeans ->
Binary image
檢測(cè)到最大包圍圈->
掩碼->
結(jié)果
Detected largest enclosing circle ->
Mask ->
Result
這是第二張圖片的輸出
輸入圖像->
Kmeans ->
二值圖像
Input image ->
Kmeans ->
Binary image
檢測(cè)到最大包圍圈->
掩碼->
結(jié)果
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()
這篇關(guān)于從圖像opencv python中刪除背景顏色的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!