2014-05-15 85 views
3

我想使用OpenCV检测与场景中其他元素明显不同的对象,因为它是灰色的。这很好,因为我可以用R == G == B来运行一个测试,并且它允许独立于亮度,但是逐个像素地执行是很慢的。使用OpenCV检测灰色物体

有没有更快的方法来检测灰色的东西?也许有一种OpenCV方法可以进行R == G == B测试...... cv2.inRange确实可以进行颜色阈值处理,这并不完全符合我的要求。

+1

如何分割图像I - >(A,B,C),然后检查[(A-B)+(A-C)] == 0? (首先将图像转换为签名格式)。你会避免逐像素的事情。 –

+1

或;拆分图像,使用absdiff并限制图像。 – Nallath

+0

hmmm,如果R == G == B,则2R-G-B = 0。如何计算2R-G-B然后使用countNonZero?只是一个预感。 – GilLevi

回答

7

我可以在Python找到的最快的方法是使用切片给每个信道进行比较。经过几次测试后,此方法比两个嵌套for循环快200倍以上。

bg = im[:,:,0] == im[:,:,1] # B == G 
gr = im[:,:,1] == im[:,:,2] # G == R 
slices = np.bitwise_and(bg, gr, dtype= np.uint8) * 255 

这将生成一个二进制图像,灰色物体用白色像素表示。如果不需要的二进制图像,但仅以灰度像素由True值指示的逻辑阵列,此方法获得更快:

slices = np.bitwise_and(bg, gr) 

省略类型转换和乘法产生一个方法比嵌套快500倍循环。

该测试图像上运行此操作:

image with gray object

给出以下结果:

gray object detection mask

正如你可以看到,灰度对象被正确检测。

+0

很适合给Python代码 – remi

1

我很惊讶,这样一个简单的检查很慢,可能你没有有效地编码它。

这是一段代码,应该为你做。它既不最佳的速度,也没有在内存中,但相当的代码:)

std::vector<cv::Mat> planes; 
cv::split(image, planes); 
cv::Mat mask = planes[0] == planes[1]; 
mask &= planes[1] == planes[2]; 

线的缘故吧的数量,这里的东西比较这将是做到这一点,我认为最快的方法(没有并行化)

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 

#include <iostream> 
#include <vector> 

#include <sys/time.h> //gettimeofday 

static 
double 
P_ellapsedTime(struct timeval t0, struct timeval t1) 
{ 
    //return ellapsed time in seconds 
    return (t1.tv_sec-t0.tv_sec)*1.0 + (t1.tv_usec-t0.tv_usec)/1000000.0; 
} 



int 
main(int argc, char* argv[]) 
{ 


    struct timeval t0, t1; 
    cv::Mat image = cv::imread(argv[1]); 
    assert(image.type() == CV_8UC3); 
    std::vector<cv::Mat> planes; 
    std::cout << "Image resolution=" << image.rows << "x" << image.cols << std::endl; 
    gettimeofday(&t0, NULL); 
    cv::split(image, planes); 
    cv::Mat mask = planes[0] == planes[1]; 
    mask &= planes[1] == planes[2]; 
    gettimeofday(&t1, NULL); 
    std::cout << "Time using split: " << P_ellapsedTime(t0, t1) << "s" << std::endl; 

    cv::Mat mask2 = cv::Mat::zeros(image.size(), CV_8U); 
    unsigned char *imgBuf = image.data; 
    unsigned char *maskBuf = mask2.data; 
    gettimeofday(&t0, NULL); 
    for (; imgBuf != image.dataend; imgBuf += 3, maskBuf++) 
    *maskBuf = (imgBuf[0] == imgBuf[1] && imgBuf[1] == imgBuf[2]) ? 255 : 0; 
    gettimeofday(&t1, NULL); 
    std::cout << "Time using loop: " << P_ellapsedTime(t0, t1) << "s" << std::endl; 

    cv::namedWindow("orig", 0); 
    cv::imshow("orig", image); 
    cv::namedWindow("mask", 0); 
    cv::imshow("mask", mask); 
    cv::namedWindow("mask2", 0); 
    cv::imshow("mask2", mask2); 
    cv::waitKey(0); 

} 

台的图像上:

Image resolution=3171x2179 
Time using split: 0.06353s 
Time using loop: 0.029044s