简体   繁体   English

在OPEN CV PYTHON中识别颜色检测中的圆圈

[英]Recognize a circle in color detection in OPEN CV PYTHON

I have a code here that detects LASER light but I'm experiencing problems in different light conditions. 我这里有一个可检测激光光的代码,但是在不同的光照条件下遇到问题。 So I think I might solve it if I added a code that checks if that light is a circle. 因此,我想如果添加代码检查该灯是否为圆形,可能会解决。

The problem is I don't know how to apply it here. 问题是我不知道如何在这里应用它。 Here is what the laser light looks like in the mask. 这是激光在面罩中的样子。

I'm hoping that you can help me with my code. 我希望您能为我的代码提供帮助。

Here's my code: 这是我的代码:

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) convert from bgr to hsv color space

    lower = np.array([0,0,255]) #range of laser light
    upper = np.array([255, 255, 255])

    mask = cv2.inRange(hsv, lower, upper) 
    maskcopy = mask.copy()

    circles = cv2.HoughCircles(maskcopy, cv2.HOUGH_GRADIENT, 1, 500,
                      param1 = 20, param2 = 10,
                      minRadius = 1, maxRadius = 3)
    _,cont,_ = cv2.findContours(maskcopy, cv2.RETR_LIST,
                            cv2.CHAIN_APPROX_SIMPLE)
    if circles is not None:
        circles = np.round(circles[0,:]).astype('int')

        for(x,y,r) in circles:
            cv2.circle(frame, (x,y), r, (0,255,0),4)

    cv2.imshow('mask', mask)
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

Screenshot: 截图:

在此处输入图片说明

I tried something similar once and the best solution for me was: 我曾经尝试过类似的方法,而对我来说最好的解决方案是:

(I saved your image to my hard disk and made a sample code) (我将您的图像保存到硬盘上并制作了示例代码)

import cv2
import math

img = cv2.imread('laser.jpg')
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray_image,100,255,cv2.THRESH_BINARY)
im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
area = sorted(contours, key=cv2.contourArea, reverse=True)
contour = area[0]
(x,y),radius = cv2.minEnclosingCircle(contour)
radius = int(radius)
area = cv2.contourArea(contour)
circ = 4*area/(math.pi*(radius*2)**2)
cv2.drawContours(img, [contour], 0, (0,255,0), 2)
cv2.imshow('img', img)
print(circ)

So the idea is to find your contour with cv2.findContours (laser point) and enclosing circle to it so you can get the radius, then get the area with cv2.contourArea of your contour and check its circularity with the formula circ = 4*area/(math.pi*(radius*2)**2) . 因此,想法是使用cv2.findContours (激光点)查找轮廓并将其包围起来,以便获得半径,然后使用cv2.contourArea获取轮廓的面积,并使用公式circ = 4*area/(math.pi*(radius*2)**2)检查其圆度circ = 4*area/(math.pi*(radius*2)**2) The perfect citrcle would return the result of 1. The more it goes to 0 the less "circuar" your contour is (in pictures below). 完美的循环将返回1的结果。0越大,轮廓越“圆”(在下面的图片中)。 Hope it helps! 希望能帮助到你!

在此处输入图片说明

在此处输入图片说明

so your code should be something like this and it will return no error (tried it and it works) 因此您的代码应该是这样的,并且不会返回任何错误(尝试过并且可以使用)

import cv2
import numpy as np
import math

cap = cv2.VideoCapture(0)

while True:
    try:
        ret, frame = cap.read()
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) #convert from bgr to hsv color space

        lower = np.array([0,0,255]) #range of laser light
        upper = np.array([255, 255, 255])

        mask = cv2.inRange(hsv, lower, upper) 

        im2, contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
        area = sorted(contours, key=cv2.contourArea, reverse=True)
        contour = area[0]
        (x,y),radius = cv2.minEnclosingCircle(contour)
        radius = int(radius)
        area = cv2.contourArea(contour)
        circ = 4*area/(math.pi*(radius*2)**2)
        print(circ)
    except:
        pass

    cv2.imshow('mask', mask)
    cv2.imshow('frame', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

I came up with a solution with a different approach. 我想出了一种使用不同方法的解决方案。

My idea was to create a circle with center in the center of the white region of the mask and with radius equal to half the width of the white region of the mask. 我的想法是创建一个圆,其中心位于蒙版的白色区域的中心,半径等于蒙版的白色区域的宽度的一半。 Then I check how similar is this circle from the mask. 然后我检查面具上的这个圆圈有多相似。

Here is the code: 这是代码:

white = np.where(mask>250) # you can also make it == 255
white = np.asarray(white)
minx = min(white[0])
maxx = max(white[0])
miny = min(white[1])
maxy = max(white[1])
radius = int((maxx-minx)/2)
cx = minx + radius
cy = miny + radius
black = mask.copy()
black[:,:]=0
cv2.circle(black, (cy,cx), radius, (255,255,255),-1)
diff = cv2.bitwise_xor(black, mask)
diffPercentage = len(diff>0)/diff.size
print (diffPercentage)

Then you have to come up with what percentage threshold is "similar" enough for you. 然后,您必须提出一个百分比阈值“足够”适合您。

The code above was tested reading a mask from disk, but a video is just a sequence of images. 上面的代码已经过测试,可以从磁盘读取掩码,但是视频只是图像序列。 Without your webcam input I cannot test the code with video, but it should work like this: 没有您的网络摄像头输入,我无法使用视频测试代码,但是它应该像这样工作:

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower = np.array([0,0,255]) #range of laser light
    upper = np.array([255, 255, 255])

    mask = cv2.inRange(hsv, lower, upper) 
    white = np.where(mask>250) # you can also make it == 255
    white = np.asarray(white)
    minx = min(white[0])
    maxx = max(white[0])
    miny = min(white[1])
    maxy = max(white[1])
    radius = int((maxx-minx)/2)
    cx = minx + radius
    cy = miny + radius
    black = mask.copy()
    black[:,:]=0
    cv2.circle(black, (cy,cx), radius, (255,255,255),-1)
    diff = cv2.bitwise_xor(black, mask)
    diffPercentage = len(diff>0)/diff.size
    print (diffPercentage)

    cv2.imshow('mask', mask)
    cvw.imshow('diff', diff)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM