2014-05-15 4 views
3

OpenCV를 사용하여 회색의 장면에서 다른 요소와 분명히 다른 개체를 감지하고 싶습니다. 이것은 R == G == B로 테스트를 수행 할 수 있고 광도와 독립적이 될 수 있기 때문에 좋지만 픽셀 단위로 처리하는 것은 느립니다.OpenCV로 회색 사물을 감지하십시오.

회색 사물을 더 빠르게 감지 할 수 있습니까? 어쩌면 R == G == B 테스트를하는 OpenCV 메소드가 있습니다 ... cv2.inRange은 색상 임계 값을 설정합니다.

+1

분할 이미지 I -> (A, B, C)를 확인한 다음 [(A-B) + (A-C)] == 0을 확인하는 것은 어떻습니까? (이미지를 서명 된 형식으로 먼저 변환하십시오). 당신은 pixel by pixel을 피할 것입니다. –

+1

또는; 이미지를 분할하고 absdiff를 사용하고 이미지를 임계 값으로 설정합니다. – Nallath

+0

흠. R == G == B이면 2R-G-B = 0. 2R-G-B를 계산 한 다음 countNonZero를 사용하는 것은 어떻습니까? 단지 직감. – GilLevi

답변

7

내가 파이썬에서 찾을 수있는 가장 빠른 방법은 각 채널을 비교하는 슬라이스를 사용하는 것입니다. 몇 번의 테스트를 실행 한 후에이 방법은 두 개의 중첩 된 for-loops보다 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 

이렇게하면 회색 객체가 흰색 픽셀로 표시되는 이진 이미지가 생성됩니다.

slices = np.bitwise_and(bg, gr) 

유형 캐스트를 생략하고 곱하기 500 배 빠른 중첩보다 방법을 산출한다 : 당신은 바이너리 이미지,하지만 회색 픽셀이 True 값으로 표시됩니다 만 논리적 배열이 필요하지 않은 경우,이 방법은 더 빨리 도착 루프. 이 테스트 이미지에서이 작업을 실행

:

image with gray object

는 다음과 같은 결과를 제공합니다 :

gray object detection mask

당신이 볼 수 있듯이, 회색 물체가 제대로 감지된다.

+0

파이썬 코드를 제공하기에 좋음 – 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