【问题标题】:Detecting colored objects and focused on the camera with OpenCv使用 OpenCv 检测有色物体并聚焦在相机上
【发布时间】:2014-10-08 04:38:23
【问题描述】:

我需要一些项目帮助。它是关于在确定的绿色区域中检测红色物体。我必须躲避物体并到达目标(在本例中为蓝色区域),还必须使用伺服电机和夹具返回收集物体,所有这些都使用带有 OpenCv 和 Irobot 的相机。

到目前为止,我拥有的代码可以识别红色对象,并移动到它们并在它们靠近时停止。也可以左右旋转,我这样做是为了尝试将相机中的物体居中,将屏幕分成3部分,然后我用伺服拾取它。但是我没有想法,当我运行 de python 代码时,过程非常缓慢,并且左右侧的检测非常敏感,我无法将对象聚焦在中心。另外我不知道如何获得物体和 irobot 之间的距离,理论上我可以躲避物体,但不知道如何到达目标,或者如何回到目标。

这是python代码:

    import cv2
    import numpy as np
    import serial
    from time import sleep

    def serialCom(int):
        ser =  serial.Serial(port = "/dev/ttyACM0", baudrate=9600)
        x = ser.readline()
        ser.write(int)
        x = ser.readline()
        print 'Sending: ', x

    # Recognizes how much red is in a given area by the parameters
    def areaRed(img, xI, xF, yI, yF): 

        # counter red pixels
        c = 0
        red = 255 

        for i in range(xI, xF):
            for j in range(yI, yF):
                if img[i][j] == red:
                    c += 1

        return c


    def reconoce(lower_re, upper_re, lower_gree, upper_gree, lower_ble, upper_ble):
        cap = cv2.VideoCapture(1)

        while(1):
            _, frame = cap.read()

            # Converting BGR to HSV
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            hsv2 = cv2.cvtColor(frame , cv2.COLOR_BGR2HSV)
            hsv3 = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

            # Threshold the HSV image to get only red,blue and green colors
            mask = cv2.inRange(hsv, lower_re, upper_re)
            maskBlue = cv2.inRange(hsv2, lower_ble, upper_ble)
            maskGreen = cv2.inRange(hsv3, lower_gree, upper_gree)

            moments = cv2.moments(mask)
            area = moments['m00']
            blueMoment = cv2.moments(maskBlue)
            blueArea = blueMoment['m00']
            greenMoment = cv2.moments(maskGreen)
            greenArea = greenMoment['m00']

            # Determine the limits of the mask
            x = mask.shape[0] - 1
            y = mask.shape[1] - 1

            # Determine the center point of the image
            xC = x / 2
            yC = y / 2

            x3 = (x/3)/2
            y3 = y/2

            # Define the variables for the center values ​​of the camera
            xI, xF, yI, yF = xC - (xC / 4), xC + (xC / 4), yC - (yC / 4), yC + (yC / 4)

            #  define the ranges of the mask for the left and right side
            right = areaRed(mask, xI + (x/4), xF + (x/4), yI + (x/4), yF + (x/4))
            left = areaRed(mask, xI - (x/4), xF - (x/4), yI - (x/4), yF - (x/4))

            centro = areaRed(mask, xI, xF, yI, yF)

            if right > 700:
                serialCom ("4")
                print "turning right"
                return mask
            if left > 700:
                serialCom("5")
                print "turning left"
                return mask

            #if there is a red objet
            if centro > 5000: 
                print 'i detect red'
                #and in on the a green area
                if greenArea > 10000000:
                    #we stop the irbot
                    serialCom("1") 
                    print 'I found red and is in the area'
                    cv2.destroyAllWindows()
                    return mask
                else:
                    #then we continue moving
                    serialCom("3")
                    print ''
            else:
                print "there is not red objet:v"


            cv2.imshow('frame',frame)
            cv2.imshow('red',mask)
            k = cv2.waitKey(5) & 0xFF
            if k == 27:
                break

        cv2.destroyAllWindows()


    # The range of colors are defined for the HSV
    lower_red = np.array([170,150,50])
    upper_red = np.array([179,255,255])
    lower_green = np.array([85,80,150])
    upper_green = np.array([95,255,255])
    lower_blue = np.array([100,100,100])
    upper_blue = np.array([120,255,255])


    while True:
        img = reconoce(lower_red, upper_red, lower_green, upper_green, lower_blue, upper_blue)
        cv2.imshow('Freeze image', img)
        cv2.waitKey(10000)
        cv2.destroyAllWindows()

这是连接 irobot 和 opencv 的 arduino 代码

#include <Roomba.h>

Roomba roomba(&Serial1);
int p=0;

void init()
{
  roomba.driveDirect(-100,100);
  roomba.driveDirect(-100,100);
  delay(100);
  roomba.driveDirect(100,-100);
  delay(100);
}

void move()
{
  roomba.driveDirect(50,50);
  roomba.driveDirect(50,50);  
}

void reverse()
{
  roomba.driveDirect(-50,-50);
}

void left_rotation()
{
  roomba.driveDirect(-30,30);
  delay(1000);
}

void right_rotation()
{
  roomba.driveDirect(30,-30);
  delay(1000);
}

void stop()
{
  roomba.driveDirect(0,0);
  delay(500);
  Serial.println("9");
}


void setup()
{

  Serial.begin(9600);
  roomba.start();
  roomba.safeMode();

}

void loop()
{

  if(Serial.available()>0)
  {

    p=Serial.read();

    if(p == 51)
    {
      Serial.println("1");
      move();   
    }

    if(p==50)
    {
      Serial.println("2");
      reverse();
      delay(1000);
    }

    if(p==52)
    {
      Serial.println("4");
      left_rotation();
      delay(1000);
      stop();
    }

    if(p==53)
    {
      Serial.println("5");
      right_rotation();
      delay(1000);
      stop();
    }

    if(p==49)
    {
      Serial.println("3");
      stop();
      delay(1000);
    }
  }
  delay(100);
}

【问题讨论】:

    标签: python opencv arduino


    【解决方案1】:

    是的,您的代码非常慢,因为您使用自己的原始源代码手动迭代图像矩阵。我建议阅读更多关于对象跟踪和理论问题的内容,然后再阅读现有的实际解决方案。这可能比尝试在低级别使用 openCV 进行编程更好。对于您的具体问题,我建议检查 cvBlob

    http://code.google.com/p/cvblob/

    这也是关于跟踪红色物体的(即使是很酷的演示视频)。

    如果对象不仅仅是纯色而是有纹理的,我建议使用 openCV 文档的这一部分

    http://docs.opencv.org/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html

    其中解释了通过特征提取、描述符生成和 FLANN 匹配进行跟踪。

    【讨论】:

    【解决方案2】:

    我猜“如此敏感”意味着你的机器人一直在抖动,因为你的检测速度太慢,无法跟随物体的实际位置。

    首先,您需要确保可以以特定帧速率(例如 25FPS)检测目标对象。这意味着您的检测和运动动作必须在 40 毫秒内做出响应。您可以测试您的算法是否可以在 40 毫秒内完成一招。如果没有,这里有一些建议。

    您的以下代码效率不高。他们遍历图像大约 12 次,花费太多时间。为防止这种情况,您可以将遍历次数设为 2 次(或仅一次)。

            # Converting BGR to HSV
            hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            hsv2 = cv2.cvtColor(frame , cv2.COLOR_BGR2HSV)
            hsv3 = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
            # Threshold the HSV image to get only red,blue and green colors
            mask = cv2.inRange(hsv, lower_re, upper_re)
            maskBlue = cv2.inRange(hsv2, lower_ble, upper_ble)
            maskGreen = cv2.inRange(hsv3, lower_gree, upper_gree)
    
            moments = cv2.moments(mask)
            area = moments['m00']
            blueMoment = cv2.moments(maskBlue)
            blueArea = blueMoment['m00']
            greenMoment = cv2.moments(maskGreen)
            greenArea = greenMoment['m00']
    
            ...
    
            #  define the ranges of the mask for the left and right side
            right = areaRed(mask, xI + (x/4), xF + (x/4), yI + (x/4), yF + (x/4))
            left = areaRed(mask, xI - (x/4), xF - (x/4), yI - (x/4), yF - (x/4))
    
            centro = areaRed(mask, xI, xF, yI, yF)
    

    很抱歉,我现在只能用一些现有代码提供 C++ 代码。

    Mat hsv, RedMask, BlueMask, GreenMask ;
    RedMask = Mat::zeros(src.rows, src.cols, CV_8UC1) ;
    RedMask.copyTo(BlueMask);
    RedMask.copyTo(GreenMask);
    //filtering each chanel
    cvtColor (src, hsv, CV_BGR2HSV) ;
    const uchar* pix ;
    uchar * pixoutr ;
    uchar * pixoutg ;
    uchar * pixoutb ;
    
    long int redarea = 0 ;
    long int greenarea = 0 ;
    long int bluearea = 0 ;
    
    for (int i = 0 ; i < hsv.rows ; i++)
    {
        pix = hsv.ptr<uchar>(i) ;
        pixoutr = RedMask.ptr<uchar>(i) ;
        pixoutg = GreenMask.ptr<uchar>(i) ;
        pixoutb = BlueMask.ptr<uchar>(i) ;
    
        for (int j=0 ; j < hsv.cols * hsv.channels() ; j+=hsv.channels())
        {
            if (pix[j] >= lower_blue || pix[j] <= higer_blue)
            {
                pixoutb[(int)j/hsv.channels()] = 255 ;
                bluearea+=1 ;
            }
            if (pix[j+1] >= lower_gree || pix[j+1] <= higer_gree)
            {
                pixoutg[(int)j/hsv.channels()] = 255 ;
                greenarea+=1 ;
            }
            if (pix[j+2] >= lower_re || pix[j+2] <= higer_re)
            {
                pixoutr[(int)j/hsv.channels()] = 255 ;
                bluearea+=1;
            }
    
        }
    }
    

    所以你得到所有通道掩码和只有一次遍历的区域。如果应用 OpenMP 或 python 多线程技术,速度会更快。

    另外你的跟踪算法有很多问题,请看一下图像相关性/斑点跟踪等。对于你的 HU 时刻使用,方向是正确的,因为它足够快。实时特征检测现在对你来说不是很实用。最后,请注意您应该安排您的 OpenCV 检测算法与您的 adrino 动作代码并行发生,您可以为此使用简单的线程技术,这样您就可以在伺服电机运行时利用计算时间。

    补充:

    http://openmp.org/wp/resources/ 用于 OpenMP,http://opencv.jp/?s=OpenMP 是带有 OpenMP 的 OpenCV 示例,opencv python Multi Threading Video Capture 是带有 OpenCV 的 python 线程技术,另一个答案已经给出了 blob 跟踪示例。图片相关模板匹配方法请查看http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

    【讨论】:

    • 你有任何文档或链接,我可以在其中使用 python、th OpenMp 和相关/blob trackind 检查多线程,这将有很多帮助
    • 我在上面添加了一些内容。
    猜你喜欢
    • 2012-12-30
    • 2021-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-26
    • 2012-07-06
    • 2014-10-13
    • 1970-01-01
    相关资源
    最近更新 更多