任何照明(低或高)中物体的图像分割

时间:2018-06-19 09:13:09

标签: python-3.x opencv image-processing image-segmentation

我手头的问题是在白球周围画出边界。但是球存在于不同的照明中。使用canny边缘检测和Hough变换用于圆圈,我能够在明亮的光线/部分明亮的光线下检测球,但不能在低照度下检测球体。

所以任何人都可以帮助解决这个问题。 我尝试过的代码如下。

img=cv2.imread('14_04_2018_10_38_51_.8242_P_B_142_17197493.png.png')
cimg=img.copy()
img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.medianBlur(img,5)
edges=cv2.Canny(edges,200,200)
circles = cv2.HoughCircles(edges,cv2.HOUGH_GRADIENT,1,20,
                        param1=25,param2=10,minRadius=0,maxRadius=0)

if circles is not None:
     circles = np.uint16(np.around(circles))
     for i in circles[0,:]:
         # draw the outer circle
         cv2.circle(cimg,(i[0],i[1]),i[2],(255,255,255),2)
         # draw the center of the circle
         cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
     cv2.imwrite('segmented_out.png',cimg)
else:
    print("no circles")
cv2.imwrite('edges_out.png',edges)

在下图中,我们需要分割球是否也在阴影区域。

input image

输出应该类似于下面的图像..

output

3 个答案:

答案 0 :(得分:2)

嗯,我对OpenCV或Python的经验不是很丰富,但是我也在学习。可能不是很Python的代码,但是您可以尝试以下方法:

import cv2
import math

circ=0
n = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220]
img = cv2.imread("ball1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
for i in n:   
    ret, threshold = cv2.threshold(gray,i,255,cv2.THRESH_BINARY)
    im, contours, hierarchy = cv2.findContours(threshold,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    for j in range(0, len(contours)):
        size = cv2.contourArea(contours[j])
        if 500 < size < 5000:
            if circ > 0:
                (x,y),radius = cv2.minEnclosingCircle(contours[j])
                radius = int(radius)
                area = cv2.contourArea(contours[j])
                circif = 4*area/(math.pi*(radius*2)**2)
                if circif > circ:
                    circ = float(circif)
                    radiusx = radius
                    center = (int(x),int(y))                  
            elif circ == 0:
                (x,y),radius = cv2.minEnclosingCircle(contours[j])
                radius = int(radius)
                area = cv2.contourArea(contours[j])
                circ = 4*area/(math.pi*(radius*2)**2)
            else:
                pass
cv2.circle(img,center,radiusx,(0,255,0),2)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.detroyAllWindows()

它的作用是正确地将图片转换为灰度并对其应用不同的阈值设置。然后,通过增加特定轮廓的尺寸来消除噪声。找到它后,检查其圆度(注意:这不是科学公式),并将其与下一个圆度进行比较。完美圆应该返回结果1,所以轮廓(所有轮廓中)中的最高数字将是您的球。

结果:

enter image description here

enter image description here

enter image description here

enter image description here

注意:我没有尝试增加大小限制,因此如果您具有高分辨率图片,则更高的限制可能会返回更好的结果

答案 1 :(得分:1)

使用grayscale图片会让您受到不同光线条件的影响。

要免于此操作,我建议您使用HSV色彩空间,然后使用Hue组件代替grayscale图片。

Hue独立于光照条件,因为它为您提供有关颜色的信息,无论其SaturationValue(与图像亮度相关的值)。

This可能会让您对色彩空间有所了解,最适合用于图像分割。

答案 2 :(得分:0)

在您的情况下。我们有一个白色的球。
White本身并不是一种颜色。
这里的主要因素是,white ball
上的光线实际上是什么样的像上面@magicleon

所提到的那样,落在它上面的光线会直接影响您可能打算使用像HSV这样的color space进行的提取类型

HSV是您在此处进行细分的最佳选择。
使用
whiteObject = cv2.inRange(hsvImage,lowerHSVLimit,upperHSVLimit)
lowerHSVLimitupperHSVLimit HSV颜色范围

牢记条件
1)单击时图像具有相似的条件
2)您可以在提取前涵盖所有HSV范围

希望您有个好主意

考虑此示例

enter image description here

hue45范围内选择特定的60

代码

image = cv2.imread('allcolors.png')

hsvImg = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)

lowerHSVLimit = np.array([45,0,0])
upperHSVLimit = np.array([60,255,255])

colour = cv2.inRange(hsvImg,lowerHSVLimit,upperHSVLimit)

plt.subplot(111), plt.imshow(colour,cmap="gray")
plt.title('hue range from 45 to 60'), plt.xticks([]), plt.yticks([])
plt.show()

这里的色相是从4560

enter image description here