使用Open CV获取轮廓内的平均颜色

时间:2019-01-22 21:18:33

标签: python opencv opencv-contour

所以我决定开始一起学习Open CV和Python!

我的第一个项目是在相对静止的背景下检测运动对象,然后检测其平均颜色以对其进行排序。至少有10个物体要检测,我正在处理彩色视频。

到目前为止,我设法去除了背景,确定了轮廓(可以选择获取每个轮廓的中心),但是现在我正在努力获取每个轮廓内部的平均颜色或平均颜色。关于此类问题,有一些主题,但大多数都是用C编写的。显然,我可以使用cv.mean(),但无法获得有效的掩模来输入此函数。我想这并不困难,但是我被困在那里...干杯!

import numpy as np
import cv2

video_path = 'test.h264'

cap = cv2.VideoCapture(video_path)
fgbg = cv2.createBackgroundSubtractorMOG2()


while (cap.isOpened):

    ret, frame = cap.read()
    if ret==True:
        fgmask = fgbg.apply(frame)
        (contours, hierarchy) = cv2.findContours(fgmask, cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)

        for c in contours:
            if cv2.contourArea(c) > 2000:
                cv2.drawContours(frame, c, -1, (255,0,0), 3)
        cv2.imshow('foreground and background',fgmask)
        cv2.imshow('rgb',frame)

    key = cv2.waitKey(1) & 0xFF

    if key == ord("q"):
        break

cap.release()
cv2.destroyAllWindows()

2 个答案:

答案 0 :(得分:2)

您可以先创建一个与输入图像具有相同尺寸且像素值设置为零的新图像来创建蒙版。

然后将轮廓绘制到像素值为255的图像上。所得图像可用作蒙版。

mask = np.zeros(frame.shape, np.uint8)
cv2.drawContours(mask, c, -1, 255, -1)
然后

mask可以用作cv.mean的参数

mean = cv.mean(frame, mask=mask)

仅需注意,RGB颜色的平均值并不总是有意义。也许尝试转换为HSV颜色空间,而仅使用H通道检测对象的颜色。

答案 1 :(得分:0)

图像解决方案

1)查找轮廓(在这种情况下为矩形,非矩形的轮廓很难制作)

2)找到轮廓的坐标轴

3)从轮廓上剪切图像

4)对各个通道求和,然后将其除以其中的像素数(或使用均值函数)

import numpy as np
import cv2
img = cv2.imread('my_image.jpg',1)
cp = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(cp,150,255,0)
cv2.imshow('img',thresh) 
cv2.waitKey(0)
im2,contours,hierarchy = cv2.findContours(thresh.astype(np.uint8), 1, 2)
cnts = contours
for cnt in cnts:
    if cv2.contourArea(cnt) >800: # filter small contours
        x,y,w,h = cv2.boundingRect(cnt) # offsets - with this you get 'mask'
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
        cv2.imshow('cutted contour',img[y:y+h,x:x+w])
        print('Average color (BGR): ',np.array(cv2.mean(img[y:y+h,x:x+w])).astype(np.uint8))
        cv2.waitKey(0)
cv2.imshow('img',img) 
cv2.waitKey(0)
cv2.destroyAllWindows()

要消除噪音,您只需将轮廓的中心,然后将较小的矩形检查一下即可。

对于非矩形轮廓,请查看cv2.fillPoly函数-> Cropping non rectangular contours但是它的算法有点慢(但没有限制)

如果您对非矩形轮廓感兴趣,则必须谨慎对待均值,因为您将需要蒙版,并且蒙版/背景始终为矩形,因此您将对不需要的对象进行均化