【问题标题】:How to discard the edges of an image using opencv?如何使用opencv丢弃图像的边缘?
【发布时间】:2018-10-17 04:36:26
【问题描述】:

我正在预处理一些图像,以便从我感兴趣的区域中移除背景。然而,由于相机的对焦,我长凳上的图像边缘呈圆形。如何丢弃这些圆形边缘并仅从图像中删除我感兴趣的对象?下面的代码我可以去除图像的背景,但由于周围的边缘,它不能正常工作。

import numpy as np
import cv2

#Read the image and perform threshold and get its height and weight
img = cv2.imread('IMD408.bmp')
h, w = img.shape[:2]

# Transform to gray colorspace and blur the image.
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)

# Make a fake rectangle arround the image that will seperate the main contour.
cv2.rectangle(blur, (0,0), (w,h), (255,255,255), 10)

# Perform Otsu threshold.
_,thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)

# Create a mask for bitwise operation
mask = np.zeros((h, w), np.uint8)

# Search for contours and iterate over contours. Make threshold for size to
# eliminate others.
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

for i in contours:
    cnt = cv2.contourArea(i)
    if 1000000 >cnt > 100000:
        cv2.drawContours(mask, [i],-1, 255, -1)


# Perform the bitwise operation.
res = cv2.bitwise_and(img, img, mask=mask)

# Display the result.
cv2.imwrite('IMD408.png', res)
cv2.imshow('img', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

输入图像:

退出:

错误:

【问题讨论】:

  • 你想要什么输出?最简单的方法是将图像裁剪得更小,如果每个图像的圆角边缘都相同,您可以硬编码要裁剪多少。
  • 我更新了问题
  • 所有输入图像中较暗的晕影是否相同?您可以创建一个在阈值操作之前应用的图像蒙版以使角落变亮。
  • 是的,所有图片都有这个同色调的贴纸

标签: python image opencv image-processing


【解决方案1】:

既然您提到所有图像都具有相同的色调,那么这对它们应该很有效。步骤是做一些白平衡,这将增加一点对比度。

获取灰度。

阈值灰度图像。小于 127 的值设置为 255(白色)。这将为您提供一个二进制图像,它将成为原始图像的掩码。

敷面膜

如果您想获得更好的结果,您可能不得不使用阈值,这里是link。但这应该让你开始。与您相比,我使用的是不同的 OpenCV 版本,您可能需要稍微调整一下代码。

import cv2

def equaliseWhiteBalance(image):
    ''' Return equilised WB of an image '''
    wb = cv2.xphoto.createSimpleWB()                        #Create WB Object
    imgWB = wb.balanceWhite(img)                            #Balance White on image
    r,g,b = cv2.split(imgWB)                                #Get individual r,g,b channels
    r_equ  = cv2.equalizeHist(r)                            #Equalise RED channel
    g_equ  = cv2.equalizeHist(g)                            #Equalise GREEN channel
    b_equ  = cv2.equalizeHist(b)                            #Equalise BLUE channel
    img_equ_WB = cv2.merge([r_equ,g_equ,b_equ])             #Merge equalised channels
    return imgWB

#Read the image
img = cv2.imread('IMD408.bmp')
result = img.copy()

#Get whiteBalance of image
imgWB = equaliseWhiteBalance(img)

cv2.imshow('img', imgWB)
cv2.waitKey(0)

# Get gray image
gray = cv2.cvtColor(imgWB,cv2.COLOR_RGB2GRAY)
cv2.imshow('img', gray)
cv2.waitKey(0)

# Perform threshold
_, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv2.imshow('img', thresh)
cv2.waitKey(0)

# Apply mask
result[thresh!=0] = (255,255,255)

cv2.imshow('img', result)
cv2.waitKey(0)

如果每个图像的所有暗角晕影都有不同的大小,那么我建议在二进制(蒙版)图像上寻找轮廓的质心。距图像任何角落“短”距离的质心将是深色晕影,因此它们的值可以从黑色更改为白色。

【讨论】:

  • 您应该应用一个额外的蒙版来消除角落中的深色晕影,因为它们不包含任何有用的数据。由于这些在每张图像中都是相同的,因此根据 OP,您可以为每张图像重复使用固定蒙版。
  • 你需要opencv-contrib。我注意到您更改了原始图像。我正要建议添加一个遮罩,根据@HåkenLid 的建议剪掉角落我不确定它是否适用于您发布的新图片
  • @epistemophiliac 是,我改变了,因为我发现这个更像其他所有图像,而这张图像还有另一个问题,感兴趣区域 (ROI) 与我不感兴趣的圆形边框混合
  • xphoto 从您的计算机中丢失,它位于 opencv-contrib 包中。您更改为的图像更具挑战性。从二值图像中,您需要扩大像素值。这将有助于将角落与我认为您感兴趣的中心断开。
  • opencv-contrib 包括附加到 cv2 的命名空间,包括 cv2.xphoto,在这个答案中用于白平衡调整。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-07
  • 2014-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-20
相关资源
最近更新 更多