python-3.x - 任何光照(低或高)下物体的图像分割

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

我手头的问题是在一个白球周围画出边界。但是球存在于不同的照明中。对圆使用精明的边缘检测和霍夫变换,我能够在强光/部分强光下检测到球,但不能在低照度下检测到球。

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

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

最佳答案

嗯,我在 OpenCV 或 Python 方面不是很有经验,但我也在学习。可能不是很 pythonic 的一段代码,但你可以试试这个:

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

注意:我没有尝试增加尺寸限制,所以如果您有高分辨率图片,更高的限制可能会返回更好的结果

关于python-3.x - 任何光照(低或高)下物体的图像分割,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50924629/

相关文章:

python-3.x - 断言失败: [Condition x == y did not hold element-wise:]

c++ - OpenCV2 findContours(),轮廓大小不等于层次结构大小

algorithm - 以编程方式以抽象方式无间隙地排列矩形 UI 对象

c++ - 如何在 C++ 或 Python 中验证图像文件的完整性?

c++ - 嵌入 Python : undefined reference to `_imp__Py_Initialize'

python - 使用 Python 抓取 Javascript 创建的动态内容

python - 如何使用原始图像(.rgb 格式)创建视频并在 python 中添加音频?

c++ - 定义清晰但角度变化的图像的图像识别

javascript - 如何使用QWebEngineView和qtwebchannel.js一步步加载javascript?

C++重新定义现有类的输出流