4

First some background

I have written a C++ function that detect an area of a certain color in an RGB image using OpenCV. The function is used to isolate a small colored area using the FeatureDetector: SimpleBlobDetector.

The problem I have is that this function is used in a crossplatform project. On my OSX 10.8 machine using OpenCV in Xcode this works flawlessly. However when I try to run the same piece of code on Windows using OpenCV in Visual Studio, this code crashes whenever I use:

blobDetector.detect(imgThresh, keypoints)

with an error such as this:

OpenCV Error: Assertion failed (dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && ((((sizeof(size_t)<<28)|0x8442211) >> ((DataType<_Tp>::depth) & ((1 << 3) - 1))*4) & 15) == elemSize1()) in unknown function, file C:\slave\builds\WinInstallerMegaPack\src\opencv\modules\core\include\opencv2/core/mat.hpp, line 545

This is the only piece of OpenCV code that have given me problems so far. I tried several solutions like the ones suggested here Using FeatureDetector in OpenCV gives access violation and Access violation reading in FeatureDetector OpenCV 2.4.5 . But to no avail.

A somewhat solution to my problem was to add a threshold() call just before my call to .detect(), which appears to make it work. However I don't like this solution as it forces me to do something I don't have to (as far as I know) and because it is not necessary to do on my Mac for some reason.

Question

Can anyone explain why the following line:

threshold(imgThresh, imgThresh, 100, 255, 0);

is necessary on Windows, but not on OSX, just before the call to .detect() in the following code?

Full code snippet:

#include "ColorDetector.h"

using namespace cv;
using namespace std;

Mat ColorDetection(Mat img, Scalar colorMin, Scalar colorMax, double alpha, int beta)
{
    initModule_features2d();
    initModule_nonfree();

    //Define matrices
    Mat contrast_img = constrastImage(img, alpha, beta);
    Mat imgThresh;
    Mat blob;

    //Threshold based on color ranges (Blue/Green/Red scalars)
    inRange(contrast_img, colorMin, colorMax, imgThresh); //BGR range

    //Apply Blur effect to make blobs more coherent
    GaussianBlur(imgThresh, imgThresh, Size(3,3), 0);

    //Set SimpleBlobDetector parameters
    SimpleBlobDetector::Params params;
    params.filterByArea = false;
    params.filterByCircularity = false;
    params.filterByConvexity = false;
    params.filterByInertia = false;
    params.filterByColor = true;
    params.blobColor = 255;
    params.minArea = 100.0f;
    params.maxArea = 500.0f;

    SimpleBlobDetector blobDetector(params);
    blobDetector.create("SimpleBlob");

    //Vector to store keypoints (center points for a blob)
    vector<KeyPoint> keypoints;

    //Try blob detection
    threshold(imgThresh, imgThresh, 100, 255, 0);
    blobDetector.detect(imgThresh, keypoints);

    //Draw resulting keypoints
    drawKeypoints(img, keypoints, blob, CV_RGB(255,255,0), DrawMatchesFlags::DEFAULT);

    return blob;
}
Community
  • 1
  • 1
Dyrborg
  • 877
  • 7
  • 16
  • Sorry about the long response time. Yes I did get it to work. I am not sure why my fix work, but the issue on Windows appeared to happen when you were overriding values in the target matrix for some functions. The reason blobDetector.detect(imgThresh, keypoints) threw an exception is that GaussianBlur(imgThresh, imgThresh...) nullified the imgThresh var (thus the access violation). Calling threshold(imgThresh, imgThresh...) reinit the variable and populated it. The fix is to create a variable for every function call e.g: threshold(img, new_img_var, 100, 255, 0) and not reuse the same variable. – Dyrborg Oct 26 '14 at 12:19

1 Answers1

2

Try using it that way:

Ptr<SimpleBlobDetector> sbd = SimpleBlobDetector::create(params);
vector<cv::KeyPoint> keypoints;
sbd->detect(imgThresh, keypoints);
Gizmo
  • 871
  • 1
  • 15
  • 38