1

I'm trying to do finger recognition using opencv, which has been working correctly when simply processing one image from the capture, however after adding the while loop to have it go from single image capture to live processing, there seems to be a heap error showing. I'm currently running it on Visual Studio 2017 w/ OpenCV 3.41.

The error from the Microsoft Visual C++ Runtime Library is

Debug Assertion Failed!
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line: 996

Expression: __acrt_first_block == header

Here is the error

The code I'm using is:

#include "stdafx.h"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;

int myMax(int a, int b, int c);
int myMin(int a, int b, int c);
void mySkinDetect(Mat& src, Mat& dst);
Mat src; Mat src_gray;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
void thresh_callback(int, void*);


int main(){
    VideoCapture cap(0);
    while (1) {

        cap >> src;

        Mat frameDest;
        frameDest = Mat::zeros(src.rows, src.cols, CV_8UC1);
        mySkinDetect(src, frameDest);
        int erosion_size = 1;
        Mat element = getStructuringElement(MORPH_RECT,
            Size(2 * erosion_size + 1, 2 * erosion_size + 1),
            Point(erosion_size, erosion_size));
        erode(frameDest, frameDest, element);
        erode(frameDest, frameDest, element);
        namedWindow("Skin", WINDOW_AUTOSIZE);
        imshow("Skin", frameDest);


        blur(frameDest, src, Size(3, 3));
        createTrackbar(" Threshold:", "Source", &thresh, max_thresh, thresh_callback);
        thresh_callback(0, 0);

        if (waitKey(30) == 27) { break; }
    }
    return(0);

}
void thresh_callback(int, void*)
{
    Mat threshold_output;
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    threshold(src, threshold_output, thresh, 255, THRESH_BINARY);
    findContours(threshold_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    vector<vector<Point>>hull(contours.size());
    vector<vector<int> > hullsI(contours.size());
    vector<vector<Vec4i>>defects(contours.size());

    int index = 0;
    int area = 0;
    for (int i = 0; i < contours.size(); i++)
    {
        double a = contourArea(contours[i]);
        if (a>area)
        {
            area = a;
            index = i;
        }
    }

    for (int i = 0; i < contours.size(); i++)
        {
            convexHull(contours[i], hull[i], false);
            convexHull(contours[i], hullsI[i], false);
            if (hullsI[i].size() > 3)
            {
                convexityDefects(contours[i], hullsI[i], defects[i]);
            }
        }
    Mat drawing = Mat::zeros(threshold_output.size(), CV_8UC3);
    for (size_t i = 0; i< contours.size(); i++)
    {
        Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        drawContours(drawing, contours, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point());
        drawContours(drawing, hull, (int)i, color, 1, 8, vector<Vec4i>(), 0, Point());
    }
    int fingers = 0;
    if (area>50) 
    {
        for (int j = 0; j<defects[index].size(); ++j)
        {
            const Vec4i& def = defects[index][j];
            float depth = def[3] / 256;
            if (depth > 5) //  filter defects by depth
            {
                int start = def[0]; 
                Point ptStart(contours[index][start]);
                int end = def[1]; 
                Point ptEnd(contours[index][end]);
                int min = def[2]; 
                Point ptFar(contours[index][min]);
                line(drawing, ptStart, ptEnd, Scalar(0, 255, 0), 1);
                line(drawing, ptStart, ptFar, Scalar(0, 255, 0), 1);
                line(drawing, ptEnd, ptFar, Scalar(0, 255, 0), 1);
                circle(drawing, ptFar, 4, Scalar(0, 255, 0), 2);
                fingers += 1;
            }
        }
    }
    std::string s = std::to_string(fingers-1);
    namedWindow("Hull demo", WINDOW_AUTOSIZE);
    putText(drawing, "Number Fingers = "+s, Point(drawing.cols/1.5, drawing.rows / 10), FONT_HERSHEY_PLAIN, 1.2f, Scalar(200, 0, 0), 2);
    imshow("Hull demo", drawing);
}

int myMax(int a, int b, int c) {
    int m = a;
    (void)((m < b) && (m = b));
    (void)((m < c) && (m = c));
    return m;
}

//Function that returns the minimum of 3 integers
int myMin(int a, int b, int c) {
    int m = a;
    (void)((m > b) && (m = b));
    (void)((m > c) && (m = c));
    return m;
}

//Function that detects whether a pixel belongs to the skin based on RGB values
void mySkinDetect(Mat& src, Mat& dst) {
    //Surveys of skin color modeling and detection techniques:
    //Vezhnevets, Vladimir, Vassili Sazonov, and Alla Andreeva. "A survey on pixel-based skin color detection techniques." Proc. Graphicon. Vol. 3. 2003.
    //Kakumanu, Praveen, Sokratis Makrogiannis, and Nikolaos Bourbakis. "A survey of skin-color modeling and detection methods." Pattern recognition 40.3 (2007): 1106-1122.
    for (int i = 0; i < src.rows; i++) {
        for (int j = 0; j < src.cols; j++) {
            //For each pixel, compute the average intensity of the 3 color channels
            Vec3b intensity = src.at<Vec3b>(i, j); //Vec3b is a vector of 3 uchar (unsigned character)
            int B = intensity[0]; int G = intensity[1]; int R = intensity[2];
            if ((R > 95 && G > 40 && B > 20) && (myMax(R, G, B) - myMin(R, G, B) > 15) && (abs(R - G) > 15) && (R > G) && (R > B)) {
                dst.at<uchar>(i, j) = 255;
            }
        }
    }
}
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
rique98
  • 9
  • 1
  • 3
  • Looks like you're in Debug mode -- did you link with the debug version of OpenCV libraries? They're the one with suffix `d` in the name. – Dan Mašek Apr 03 '18 at 20:11
  • @DanMašek I added but opencv_world341d.dll and opencv_world341.dll in my x64/debug folder, as well as linked in my additional dependencies as: opencv_world341.lib;opencv_world341d.lib;%(AdditionalDependencies) – rique98 Apr 03 '18 at 21:56
  • 1
    You need just 1 for each configuration -- `opencv_world341` for Release builds, `opencv_world341d` for Debug builds. You can't mix them, the 2 C++ runtimes have slight differences which causes this sort of problems. – Dan Mašek Apr 03 '18 at 22:06
  • 1
    Just deleted my opencv_world341 that was added in additional dependencies and it's working now! Thanks!!! – rique98 Apr 03 '18 at 22:07
  • 1
    When I saw similar symptoms, it turned out the issue was that I had failed to ensure that the dynamic MSVC runtime was used. This resulted in two heaps being used, one on each side of the .dll boundary. An object constructed on one side of the .dll boundary was then being destroyed by code on the other side, causing explosion. See https://stackoverflow.com/a/35311928/ – Max Barraclough Mar 15 '20 at 18:51

0 Answers0