Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 利用圆检测和颜色检测识别物体_Python_Opencv - Fatal编程技术网

Python 利用圆检测和颜色检测识别物体

Python 利用圆检测和颜色检测识别物体,python,opencv,Python,Opencv,我使用颜色检测(特别是紫色)和圆形检测来检测下图中的花粉对象(紫色圆形) 然后我在检测到的物体上写上字母“p”。不幸的是,它没有像我预期的那样工作 如果我改变半径,我可以修复它,但这不是一个好主意,因为我仍然有许多不同半径的相似图像要处理。我想重点是如何知道这张图片中紫色的确切范围。通常,我想知道如何获得图像中任意颜色的范围。有些人给了我一个示例代码,但效果不好 这是我的节目 import cv2 import numpy as np # In[2]: path = "./sample

我使用颜色检测(特别是紫色)和圆形检测来检测下图中的花粉对象(紫色圆形)

然后我在检测到的物体上写上字母“p”。不幸的是,它没有像我预期的那样工作

如果我改变半径,我可以修复它,但这不是一个好主意,因为我仍然有许多不同半径的相似图像要处理。我想重点是如何知道这张图片中紫色的确切范围。通常,我想知道如何获得图像中任意颜色的范围。有些人给了我一个示例代码,但效果不好

这是我的节目

import cv2
import numpy as np


# In[2]:

path = "./sample.JPG"
font = cv2.FONT_HERSHEY_COMPLEX


# In[3]:

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    # initialize the dimensions of the image to be resized and
    # grab the image size
    dim = None
    (h, w) = image.shape[:2]

    # if both the width and height are None, then return the
    # original image
    if width is None and height is None:
        return image

    # check to see if the width is None
    if width is None:
        # calculate the ratio of the height and construct the
        # dimensions
        r = height / float(h)
        dim = (int(w * r), height)

    # otherwise, the height is None
    else:
        # calculate the ratio of the width and construct the
        # dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # resize the image
    resized = cv2.resize(image, dim, interpolation = inter)

    # return the resized image
    return resized


# In[4]:

iml = cv2.imread(path,cv2.IMREAD_COLOR)
img = image_resize(iml,width=960)


# In[5]:

hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hsv = cv2.medianBlur(hsv,5)
#mask = cv2.inRange(hsv, (120, 180, 50), (160, 255, 255))
mask = cv2.inRange(hsv, (105, 100,50), (160, 255, 255))

#mask = cv2.inRange(hsv, (126, 142, 57), (145, 255, 255))
#cv2.GaussianBlur(cimg, (9,9),3)
#cimg = cv2.medianBlur(cimg,5)
output = cv2.bitwise_and(hsv, hsv, mask = mask)
#circles = cv2.HoughCircles(mask[:,:,0],cv2.HOUGH_GRADIENT,1,mask.shape[0]/16,param1=15,param2=20,minRadius=18,maxRadius=38)
circles = cv2.HoughCircles(output[:,:,0],cv2.HOUGH_GRADIENT,1,output.shape[0]/16,param1=15,param2=20,minRadius=15,maxRadius=30)
print(len(circles))
circles = np.uint16(np.around(circles))[0,:]


# In[6]:

for i in circles:
     cv2.putText(img,'P',(i[0],i[1]), font, 0.5,(0,255,0),1,cv2.LINE_AA)


# In[7]:

cv2.imwrite("./result.jpg",img)

请注意,这个答案并不是一个解决方案,而是一个完成任务的新观点。即使它在某些情况下可以工作,它也可能不足以实现任何流程的自动化。也就是说,转换为HSV颜色空间的问题在于,如果图像(如您的情况)上绘制了类似的颜色对象,则很难使用
cv2.inRange()
将一个对象与另一个对象区分开来。我试图稍微修改一下你的代码,并举例说明我将如何处理这个问题

首先,您可以尝试在大津在图像上搜索所有轮廓,然后根据您选择的标准过滤出最大的(甜甜圈)和其他小的轮廓

一旦你有了它,你就可以在轮廓周围做一个ROI。然后我会尝试对每个ROI执行
cv2.inRange()

之后,我会在每个ROI上再次搜索轮廓,并计算白色像素或为轮廓制定“圆形”标准。如果他们通过,这意味着它的范围内有很多像素,并画出字母T。希望它能有所帮助。干杯

例如:

import cv2
import numpy as np


# In[2]:

path = "./purplecirc4.JPG"
font = cv2.FONT_HERSHEY_COMPLEX


# In[3]:

def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    # initialize the dimensions of the image to be resized and
    # grab the image size
    dim = None
    (h, w) = image.shape[:2]

    # if both the width and height are None, then return the
    # original image
    if width is None and height is None:
        return image

    # check to see if the width is None
    if width is None:
        # calculate the ratio of the height and construct the
        # dimensions
        r = height / float(h)
        dim = (int(w * r), height)

    # otherwise, the height is None
    else:
        # calculate the ratio of the width and construct the
        # dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # resize the image
    resized = cv2.resize(image, dim, interpolation = inter)

    # return the resized image
    return resized


# In[4]:

iml = cv2.imread(path,cv2.IMREAD_COLOR)
img = image_resize(iml,width=960)

# Threshold with OTSU to get all contours
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),0)
_,thresh = cv2.threshold(blur,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
_, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

# Empty list for contours that could be positive
ROIs=[]


# Append possible contours to list
# (I have selected height to eliminate unwanted noise)
for cnt in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    if 200 > h > 20:
        x1 = x-20
        x2 = x+w+20
        y1 = y-20
        y2 = y+h+20
        roi = img[y1:y2, x1:x2]
        ROIs.append(roi)

# Iterate through list of ROIS and transform to HSV
# (I made a little adjustment in values )
for i in ROIs:
    hsv = cv2.cvtColor(i,cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, (115,100,50), (160,255,255))
    # Search for contours on every ROI in list and select the biggest one
    _, contours, hierarchy = cv2.findContours(mask,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    cnt = max(contours, key=cv2.contourArea)
    # Draw them whole on hsv then transform to gray and perform OTSU threshold and search for contoures
    cv2.drawContours(hsv, [cnt], 0, 255, -1)
    gray = cv2.cvtColor(hsv, cv2.COLOR_BGR2GRAY)
    _,thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    _, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    cnt = max(contours, key=cv2.contourArea)
    # Make a "roundness" criterion and draw the letter
    x,y,w,h = cv2.boundingRect(cnt)
    perimeter = cv2.arcLength(cnt,True)
    radius = perimeter/(2*np.pi)
    area = cv2.contourArea(cnt)
    circ = 4*area/(np.pi*(radius*2)**2)
    if circ > 0.70:
        cv2.putText(i,'P',(int(x+(w/2.5)),int(y+(h/2))), font, 0.5,(0,255,0),1,cv2.LINE_AA)

# Display result:
resized = cv2.resize(img, (0,0), fx=0.5, fy=0.5) 
cv2.imshow("roi",resized)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:


可能重复:问题不一样。我建议仔细阅读。谢谢。试着缩小cv2的范围。在范围内,我复制了你的代码,但效果不好。没有像你展示的那样的“P”。你能再次检查你的代码吗?我检查过了,它在我的电脑上运行。我建议在for循环的每个步骤(hsv、thresh…)之前和中使用cv2.imshow()进行可视化,并查看代码的作用。请注意,正如我在帖子中提到的,这个答案并不意味着是一个完整的工作解决方案,但可能是一个新的方法来解决问题,给你一些新的想法。请记住,仅使用一个示例图像很难生成完整的工作解决方案。