如何检测与背景颜色高度相似的图像目标并实现黑白分割
问题描述
我有一张目标与背景颜色高度相似的图像,希望检测出该目标并将其设为白色,背景设为黑色。
![目标与背景高度相似的图像]
已尝试方案
- 转为灰度图后用
cv2.equalizeHist进行直方图均衡化 - 用
cv2.Canny检测边缘 - 尝试调整HSV通道,但缺乏相关经验不确定效果及操作方式
其中CLAHE能略微提升目标可见度,实现代码如下:
import cv2 import tkinter.filedialog as fd def main(): filepath = fd.askopenfilename() image = cv2.imread(filepath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=5) cla = clahe.apply(gray) cv2.imshow("Image", cla) cv2.waitKey(0) cv2.destroyAllWindows() main()
但不确定后续该如何处理以完成目标检测,寻求解决方案。
编辑补充
@Christoph Rackwitz的方案效果很好,我也找到一种基于图像处理的方法,代码如下:
import cv2 import numpy as np import tkinter.filedialog as fd def bilateral_filter(image): return cv2.bilateralFilter(image, 30, 75, 175) def enhance_image(image, h_luminance, photo_render, block_size, search_window, gamma): denoised_image = cv2.fastNlMeansDenoisingColored(image, None, h_luminance, photo_render, block_size, search_window) contrast_stretched_image = cv2.normalize(denoised_image, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1) kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32) sharpened_image = cv2.filter2D(contrast_stretched_image, -1, kernel=kernel) improved_exposure = cv2.convertScaleAbs(sharpened_image, alpha=1, beta=5) lookup_table = np.array([((i / 255.0) ** gamma) * 255 for i in np.arange(0, 256)]).astype("uint8") gamma_corrected_image = cv2.LUT(improved_exposure, lookup_table) return gamma_corrected_image def convert_to_grayscale(image): return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) def black_and_white(image): return cv2.threshold(image, 0, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)[1] def dilation(image, iter, ksize): kernel = np.ones((ksize, ksize), np.uint8) return cv2.dilate(image, kernel, iterations=iter) def erosion(image, iter, ksize): kernel = np.ones((ksize, ksize), np.uint8) return cv2.erode(image, kernel, iterations=iter) def closing(image, ksize): kernel = np.ones((ksize, ksize), np.uint8) return cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel) def sobel_filter(image): ddepth = cv2.CV_64F ksize = cv2.FILTER_SCHARR x = cv2.Sobel(image, ddepth, 1, 0, ksize=ksize, scale=1) y = cv2.Sobel(image, ddepth, 0, 1, ksize=ksize, scale=1) absx = cv2.convertScaleAbs(x) absy = cv2.convertScaleAbs(y) sobel_image = cv2.addWeighted(absx, 0.5, absy, 0.5, 0) return sobel_image def use_clahe(grayscale_image, cliplimit): clahe = cv2.createCLAHE(clipLimit=cliplimit) cla = clahe.apply(grayscale_image) return cla def process_image(image): contour_image = image.copy() sobel_image = sobel_filter(image) bilateral_image = bilateral_filter(sobel_image) h_luminance, photo_render, block_size, search_window, gamma = 7, 10, 6, 55, 5 enhanced_image = enhance_image(bilateral_image, h_luminance, photo_render, block_size, search_window, gamma) grayscale_image = convert_to_grayscale(enhanced_image) clahe_process = use_clahe(grayscale_image, 20) thres = black_and_white(clahe_process) closed = closing(thres, 20) dilated = dilation(closed, 2, 2) eroded = erosion(dilated, 1, 4) processed_image = dilation(eroded, 2, 6) contours, _ = cv2.findContours(processed_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: cv2.drawContours(contour_image, [contour], -1, [0, 0, 255], 2) return processed_image, contour_image def show_image(texts, images): for i, image in enumerate(images): cv2.imshow("{}".format(texts[i]), image) cv2.waitKey(0) cv2.destroyAllWindows() def main(): filepath = fd.askopenfilename() image = cv2.imread(filepath) processed_image, contour_image = process_image(image) texts = ["Image 1: Original", "Image 2: Processed", "Image 3: Contours"] images = [image, processed_image, contour_image] show_image(texts, images) quit() main()
该方法通过滤波器和CLAHE增强图像,再对黑白图进行形态学操作,但效果并不完美,轮廓存在偏移。目前我正尝试优化该代码并研究@Christoph Rackwitz的方案,后续会更新进展。
内容的提问来源于stack exchange,提问作者programer
相关产品推荐
相关产品推荐

