2014-05-15 125 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