2015-05-03 4 views
2

Я пытаюсь получить образец OpenCL-кода из каталогов OpenCV для работы. Образец кода «squares.cpp»:Получение NVIDIA OpenCL для работы с OpenCV 2.4.10

// The "Square Detector" program. 
// It loads several images sequentially and tries to find squares in 
// each image 

#include "opencv2/core/core.hpp" 
#include "opencv2/imgproc/imgproc.hpp" 
#include "opencv2/highgui/highgui.hpp" 
#include "opencv2/ocl/ocl.hpp" 
#include <iostream> 
#include <math.h> 
#include <string.h> 

using namespace cv; 
using namespace std; 

#define ACCURACY_CHECK 

#ifdef ACCURACY_CHECK 
// check if two vectors of vector of points are near or not 
// prior assumption is that they are in correct order 
static bool checkPoints(
    vector< vector<Point> > set1, 
    vector< vector<Point> > set2, 
    int maxDiff = 5) 
{ 
    if(set1.size() != set2.size()) 
    { 
     return false; 
    } 

    for(vector< vector<Point> >::iterator it1 = set1.begin(), it2 = set2.begin(); 
      it1 < set1.end() && it2 < set2.end(); it1 ++, it2 ++) 
    { 
     vector<Point> pts1 = *it1; 
     vector<Point> pts2 = *it2; 


     if(pts1.size() != pts2.size()) 
     { 
      return false; 
     } 
     for(size_t i = 0; i < pts1.size(); i ++) 
     { 
      Point pt1 = pts1[i], pt2 = pts2[i]; 
      if(std::abs(pt1.x - pt2.x) > maxDiff || 
        std::abs(pt1.y - pt2.y) > maxDiff) 
      { 
       return false; 
      } 
     } 
    } 
    return true; 
} 
#endif 

int thresh = 50, N = 11; 
const char* wndname = "OpenCL Square Detection Demo"; 


// helper function: 
// finds a cosine of angle between vectors 
// from pt0->pt1 and from pt0->pt2 
static double angle(Point pt1, Point pt2, Point pt0) 
{ 
    double dx1 = pt1.x - pt0.x; 
    double dy1 = pt1.y - pt0.y; 
    double dx2 = pt2.x - pt0.x; 
    double dy2 = pt2.y - pt0.y; 
    return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); 
} 


// returns sequence of squares detected on the image. 
// the sequence is stored in the specified memory storage 
static void findSquares(const Mat& image, vector<vector<Point> >& squares) 
{ 
    squares.clear(); 
    Mat pyr, timg, gray0(image.size(), CV_8U), gray; 

    // down-scale and upscale the image to filter out the noise 
    pyrDown(image, pyr, Size(image.cols/2, image.rows/2)); 
    pyrUp(pyr, timg, image.size()); 
    vector<vector<Point> > contours; 

    // find squares in every color plane of the image 
    for(int c = 0; c < 3; c++) 
    { 
     int ch[] = {c, 0}; 
     mixChannels(&timg, 1, &gray0, 1, ch, 1); 

     // try several threshold levels 
     for(int l = 0; l < N; l++) 
     { 
      // hack: use Canny instead of zero threshold level. 
      // Canny helps to catch squares with gradient shading 
      if(l == 0) 
      { 
       // apply Canny. Take the upper threshold from slider 
       // and set the lower to 0 (which forces edges merging) 
       Canny(gray0, gray, 0, thresh, 5); 
       // dilate canny output to remove potential 
       // holes between edge segments 
       dilate(gray, gray, Mat(), Point(-1,-1)); 
      } 
      else 
      { 
       // apply threshold if l!=0: 
       //  tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 
       cv::threshold(gray0, gray, (l+1)*255/N, 255, THRESH_BINARY); 
      } 

      // find contours and store them all as a list 
      findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

      vector<Point> approx; 

      // test each contour 
      for(size_t i = 0; i < contours.size(); i++) 
      { 
       // approximate contour with accuracy proportional 
       // to the contour perimeter 
       approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); 

       // square contours should have 4 vertices after approximation 
       // relatively large area (to filter out noisy contours) 
       // and be convex. 
       // Note: absolute value of an area is used because 
       // area may be positive or negative - in accordance with the 
       // contour orientation 
       if(approx.size() == 4 && 
         fabs(contourArea(Mat(approx))) > 1000 && 
         isContourConvex(Mat(approx))) 
       { 
        double maxCosine = 0; 

        for(int j = 2; j < 5; j++) 
        { 
         // find the maximum cosine of the angle between joint edges 
         double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); 
         maxCosine = MAX(maxCosine, cosine); 
        } 

        // if cosines of all angles are small 
        // (all angles are ~90 degree) then write quandrange 
        // vertices to resultant sequence 
        if(maxCosine < 0.3) 
         squares.push_back(approx); 
       } 
      } 
     } 
    } 
} 


// returns sequence of squares detected on the image. 
// the sequence is stored in the specified memory storage 
static void findSquares_ocl(const Mat& image, vector<vector<Point> >& squares) 
{ 
    squares.clear(); 

    Mat gray; 
    cv::ocl::oclMat pyr_ocl, timg_ocl, gray0_ocl, gray_ocl; 

    // down-scale and upscale the image to filter out the noise 
    ocl::pyrDown(ocl::oclMat(image), pyr_ocl); 
    ocl::pyrUp(pyr_ocl, timg_ocl); 

    vector<vector<Point> > contours; 
    vector<cv::ocl::oclMat> gray0s; 
    ocl::split(timg_ocl, gray0s); // split 3 channels into a vector of oclMat 
    // find squares in every color plane of the image 
    for(int c = 0; c < 3; c++) 
    { 
     gray0_ocl = gray0s[c]; 
     // try several threshold levels 
     for(int l = 0; l < N; l++) 
     { 
      // hack: use Canny instead of zero threshold level. 
      // Canny helps to catch squares with gradient shading 
      if(l == 0) 
      { 
       // do canny on OpenCL device 
       // apply Canny. Take the upper threshold from slider 
       // and set the lower to 0 (which forces edges merging) 
       cv::ocl::Canny(gray0_ocl, gray_ocl, 0, thresh, 5); 
       // dilate canny output to remove potential 
       // holes between edge segments 
       ocl::dilate(gray_ocl, gray_ocl, Mat(), Point(-1,-1)); 
       gray = Mat(gray_ocl); 
      } 
      else 
      { 
       // apply threshold if l!=0: 
       //  tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0 
       cv::ocl::threshold(gray0_ocl, gray_ocl, (l+1)*255/N, 255, THRESH_BINARY); 
       gray = gray_ocl; 
      } 

      // find contours and store them all as a list 
      findContours(gray, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 

      vector<Point> approx; 
      // test each contour 
      for(size_t i = 0; i < contours.size(); i++) 
      { 
       // approximate contour with accuracy proportional 
       // to the contour perimeter 
       approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true); 

       // square contours should have 4 vertices after approximation 
       // relatively large area (to filter out noisy contours) 
       // and be convex. 
       // Note: absolute value of an area is used because 
       // area may be positive or negative - in accordance with the 
       // contour orientation 
       if(approx.size() == 4 && 
         fabs(contourArea(Mat(approx))) > 1000 && 
         isContourConvex(Mat(approx))) 
       { 
        double maxCosine = 0; 
        for(int j = 2; j < 5; j++) 
        { 
         // find the maximum cosine of the angle between joint edges 
         double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1])); 
         maxCosine = MAX(maxCosine, cosine); 
        } 

        // if cosines of all angles are small 
        // (all angles are ~90 degree) then write quandrange 
        // vertices to resultant sequence 
        if(maxCosine < 0.3) 
         squares.push_back(approx); 
       } 
      } 
     } 
    } 
} 


// the function draws all the squares in the image 
static void drawSquares(Mat& image, const vector<vector<Point> >& squares) 
{ 
    for(size_t i = 0; i < squares.size(); i++) 
    { 
     const Point* p = &squares[i][0]; 
     int n = (int)squares[i].size(); 
     polylines(image, &p, &n, 1, true, Scalar(0,255,0), 3, CV_AA); 
    } 
} 


// draw both pure-C++ and ocl square results onto a single image 
static Mat drawSquaresBoth(const Mat& image, 
          const vector<vector<Point> >& sqsCPP, 
          const vector<vector<Point> >& sqsOCL 
) 
{ 
    Mat imgToShow(Size(image.cols * 2, image.rows), image.type()); 
    Mat lImg = imgToShow(Rect(Point(0, 0), image.size())); 
    Mat rImg = imgToShow(Rect(Point(image.cols, 0), image.size())); 
    image.copyTo(lImg); 
    image.copyTo(rImg); 
    drawSquares(lImg, sqsCPP); 
    drawSquares(rImg, sqsOCL); 
    float fontScale = 0.8f; 
    Scalar white = Scalar::all(255), black = Scalar::all(0); 

    putText(lImg, "C++", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, black, 2); 
    putText(rImg, "OCL", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, black, 2); 
    putText(lImg, "C++", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, white, 1); 
    putText(rImg, "OCL", Point(10, 20), FONT_HERSHEY_COMPLEX_SMALL, fontScale, white, 1); 

    return imgToShow; 
} 


int main(int argc, char** argv) 
{ 
    const char* keys = 
     "{ i | input |     | specify input image }" 
     "{ o | output | squares_output.jpg | specify output save path}" 
     "{ h | help | false    | print help message }"; 
    CommandLineParser cmd(argc, argv, keys); 
    string inputName = cmd.get<string>("i"); 
    string outfile = cmd.get<string>("o"); 

    if(cmd.get<bool>("help")) 
    { 
     cout << "Usage : squares [options]" << endl; 
     cout << "Available options:" << endl; 
     cmd.printParams(); 
     return EXIT_SUCCESS; 
    } 

    int iterations = 10; 
    namedWindow(wndname, CV_WINDOW_AUTOSIZE); 
    vector<vector<Point> > squares_cpu, squares_ocl; 

    Mat image = imread(inputName, 1); 
    if(image.empty()) 
    { 
     cout << "Couldn't load " << inputName << endl; 
     return EXIT_FAILURE; 
    } 

    int j = iterations; 
    int64 t_ocl = 0, t_cpp = 0; 
    //warm-ups 
    cout << "warming up ..." << endl; 
    findSquares(image, squares_cpu); 
    findSquares_ocl(image, squares_ocl); 


#ifdef ACCURACY_CHECK 
    cout << "Checking ocl accuracy ... " << endl; 
    cout << (checkPoints(squares_cpu, squares_ocl) ? "Pass" : "Failed") << endl; 
#endif 
    do 
    { 
     int64 t_start = cv::getTickCount(); 
     findSquares(image, squares_cpu); 
     t_cpp += cv::getTickCount() - t_start; 


     t_start = cv::getTickCount(); 
     findSquares_ocl(image, squares_ocl); 
     t_ocl += cv::getTickCount() - t_start; 
     cout << "run loop: " << j << endl; 
    } 
    while(--j); 
    cout << "cpp average time: " << 1000.0f * (double)t_cpp/getTickFrequency()/iterations << "ms" << endl; 
    cout << "ocl average time: " << 1000.0f * (double)t_ocl/getTickFrequency()/iterations << "ms" << endl; 

    Mat result = drawSquaresBoth(image, squares_cpu, squares_ocl); 
    imshow(wndname, result); 
    imwrite(outfile, result); 
    cvWaitKey(0); 

    return EXIT_SUCCESS; 
} 

Я установил рамки cuda; но я получаю следующее сообщение об ошибке при попытке запуска кода в визуальной студии 2013:

warming up ... 
OpenCV Error: Gpu API call (CL_INVALID_VALUE) in cv::ocl::ContextImpl::ContextIm 
pl, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\modules\ocl\src\cl_con 
text.cpp, line 578 
ERROR: Can't select OpenCL device: GeForce GTX 650 Ti BOOST(NVIDIA CUDA) 
ERROR: Required OpenCL device not found, check configuration: 
    Platform: any 
    Device types: GPU CPU 
    Device name: any 
OpenCV Error: Unknown error code -221 (Can't select OpenCL device) in cv::ocl::C 
ontextImpl::getContext, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\mo 
dules\ocl\src\cl_context.cpp, line 684 

UPDATE: это выход CLinfo:

Number of platforms: 1 
     CL_PLATFORM_PROFILE: FULL_PROFILE 
     CL_PLATFORM_VERSION: OpenCL 1.2 CUDA 7.0.0 
     CL_PLATFORM_VENDOR:  NVIDIA Corporation 
     CL_PLATFORM_EXTENSIONS: cl_khr_byte_addressable_store cl_khr_icd cl_khr_ 
gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unro 
ll cl_nv_d3d9_sharing cl_nv_d3d10_sharing cl_khr_d3d10_sharing cl_nv_d3d11_shari 
ng cl_nv_copy_opts 
     Number of devices:  1 
       CL_DEVICE_TYPE: CL_DEVICE_TYPE_GPU 
       CL_DEVICE_VENDOR_ID: 4318 
       CL_DEVICE_MAX_COMPUTE_UNITS: 4 
       CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:  3 
     CL_DEVICE_MAX_WORK_ITEM_SIZES: 1024 1024 64 
       CL_DEVICE_MAX_WORK_GROUP_SIZE: 1024 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: 1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: 1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: 1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: 1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: 1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:  1 
       CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: 0 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:  1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: 1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:  1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:  1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: 1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: 1 
       CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:  0 
       CL_DEVICE_MAX_CLOCK_FREQUENCY: 1097 
       CL_DEVICE_ADDRESS_BITS: 64 
       CL_DEVICE_MAX_MEM_ALLOC_SIZE: 536870912 
       CL_DEVICE_IMAGE_SUPPORT:  1 
       CL_DEVICE_MAX_READ_IMAGE_ARGS: 256 
       CL_DEVICE_MAX_WRITE_IMAGE_ARGS: 16 
       CL_DEVICE_IMAGE2D_MAX_WIDTH: 16384 
       CL_DEVICE_IMAGE2D_MAX_WIDTH: 16384 
       CL_DEVICE_IMAGE2D_MAX_HEIGHT: 16384 
       CL_DEVICE_IMAGE3D_MAX_WIDTH: 4096 
       CL_DEVICE_IMAGE3D_MAX_HEIGHT: 4096 
       CL_DEVICE_IMAGE3D_MAX_DEPTH: 4096 
       CL_DEVICE_MAX_SAMPLERS: 32 
       CL_DEVICE_MAX_PARAMETER_SIZE: 4352 
       CL_DEVICE_MEM_BASE_ADDR_ALIGN: 4096 
       CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:  128 
       CL_DEVICE_SINGLE_FP_CONFIG:  CL_FP_DENORM | CL_FP_INF_NAN | C 
L_FP_ROUND_TO_NEAREST | CL_FP_ROUND_TO_ZERO | CL_FP_ROUND_TO_INF | CL_FP_FMA 
       CL_DEVICE_SINGLE_FP_CONFIG:  CL_READ_ONLY_CACHE | CL_READ_WRI 
TE_CACHE 
       CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:  CL_READ_WRITE_CACHE 
       CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 128 
       CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:  65536 
       CL_DEVICE_GLOBAL_MEM_SIZE:  2147483648 
       CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:  65536 
       CL_DEVICE_MAX_CONSTANT_ARGS: 9 
       CL_DEVICE_LOCAL_MEM_TYPE: 
       CL_DEVICE_LOCAL_MEM_SIZE:  49151 
       CL_DEVICE_ERROR_CORRECTION_SUPPORT:  0 
       CL_DEVICE_HOST_UNIFIED_MEMORY: 0 
       CL_DEVICE_PROFILING_TIMER_RESOLUTION: 1000 
       CL_DEVICE_ENDIAN_LITTLE:  1 
       CL_DEVICE_AVAILABLE: 1 
       CL_DEVICE_COMPILER_AVAILABLE: 1 
       CL_DEVICE_EXECUTION_CAPABILITIES:  CL_EXEC_KERNEL 
       CL_DEVICE_QUEUE_PROPERTIES:  CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ 
ENABLE | CL_QUEUE_PROFILING_ENABLE 
       CL_DEVICE_PLATFORM:  000000DA609B27F0 
     CL_DEVICE_NAME: GeForce GTX 650 Ti BOOST 
     CL_DEVICE_VENDOR:  NVIDIA Corporation 
     CL_DRIVER_VERSION:  350.12 
     CL_DEVICE_PROFILE:  FULL_PROFILE 
     CL_DEVICE_VERSION:  OpenCL 1.2 CUDA 
     CL_DEVICE_OPENCL_C_VERSION:  OpenCL C 1.2 
     CL_DEVICE_EXTENSIONS: cl_khr_byte_addressable_store cl_khr_icd cl_khr_ 
gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unro 
ll cl_nv_d3d9_sharing cl_nv_d3d10_sharing cl_khr_d3d10_sharing cl_nv_d3d11_shari 
ng cl_nv_copy_opts cl_khr_global_int32_base_atomics cl_khr_global_int32_extende 
d_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl 
_khr_fp64 

, что должно быть местом для OPENCV_OPENCL_DEVICE? Я пробовал :GPU:NVIDIA, :GPU:GeForce GTX 650 Ti BOOST, :GPU:GeForce GTX 650 Ti BOOST<NVIDIA CUDA> и ошибка сохраняется!

UPDATE2: с настройками :GPU:0 и :GPU:1 я получаю следующие ошибки соответственно:

warming up ... 
OpenCV Error: Gpu API call (CL_INVALID_VALUE) in cv::ocl::ContextImpl::ContextIm 
pl, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\modules\ocl\src\cl_con 
text.cpp, line 578 
ERROR: Can't select OpenCL device: GeForce GTX 650 Ti BOOST(NVIDIA CUDA) 
ERROR: Required OpenCL device not found, check configuration: :GPU:0 
    Platform: any 
    Device types: GPU 
    Device name: 0 
OpenCV Error: Unknown error code -221 (Can't select OpenCL device) in cv::ocl::C 
ontextImpl::getContext, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\mo 
dules\ocl\src\cl_context.cpp, line 684 

и с :GPU:1 (который немного другая ошибка, длина-мудрый):

warming up ... 
ERROR: Required OpenCL device not found, check configuration: :GPU:1 
    Platform: any 
    Device types: GPU 
    Device name: 1 
OpenCV Error: Unknown error code -221 (Can't select OpenCL device) in cv::ocl::C 
ontextImpl::getContext, file C:\builds\2_4_PackSlave-win64-vc12-shared\opencv\mo 
dules\ocl\src\cl_context.cpp, line 684 

Я также сделал снимок экрана настроек среды, чтобы дважды проверить правильность этих значений:

enter image description here

+0

Пожалуйста, обратите внимание, что CUDA не имеет ничего общего с OpenCL. Я предлагаю вам получить OpenCV 3 и использовать [это руководство] (http://developer.amd.com/community/blog/2014/10/15/opencv-3-0-transparent-api-opencl-acceleration/). Работал для меня. – Antonio

+0

@antonio, но я считаю, что это cuda framework и его gdk, который позволяет opencl быть скомпилирован через его библиотеки на nvidia gpus. Потому что, как еще ты можешь! Более того, поскольку opencl-функции стали ветвью исходных функций, и они работают, если они обнаруживают библиотеки opencl в вашей системе, как вы можете быть уверены, используете ли вы предполагаемые функции opencl? –

+1

Что касается вашего последнего вопроса, единственный надежный способ - установить программное обеспечение для мониторинга графического процессора и посмотреть, эффективно ли работает GPU. CUDA и OpenCL отличаются друг от друга, NVidia предоставляет реализацию OpenCL (вы получаете ее при установке драйверов NVidia), но печальная правда заключается в том, что на самом деле они не прилагают больших усилий, несколько функций OpenCL пока недоступны для NVidia. Они поддерживают протокол OpenCL 1.2, но не 2.0. ATI поддерживает его. – Antonio

ответ

0

Проблема решается понижая драйвер NVIDIA до 344,75

1

это выглядит, как вы не удается открыть устройство, так как имя не может быть найден, или просто не в состоянии строки матча с образом парсере работы OpenCV OpenCL. Попробуйте что-то более простое.

Link to doc on setting OPENCV_OPENCL_DEVICE:

Если это не удается, дважды проверьте, что clinfo набирает устройство.

+0

Спасибо, что помогли мне, я обновил сообщение с помощью CLinfo. –

+0

Сообщение было обновлено –

Смежные вопросы