Ask Your Question

ginister's profile - activity

2020-11-09 00:02:27 -0600 received badge  Famous Question (source)
2020-07-04 12:56:00 -0600 received badge  Popular Question (source)
2019-07-15 23:42:15 -0600 received badge  Notable Question (source)
2019-02-04 09:22:32 -0600 received badge  Popular Question (source)
2018-04-11 02:57:26 -0600 received badge  Famous Question (source)
2017-11-23 00:13:27 -0600 received badge  Notable Question (source)
2017-10-01 21:08:51 -0600 received badge  Popular Question (source)
2017-03-15 06:03:11 -0600 commented answer LBP calcHist() Wrong

Argh! That's annoyingly silly. Sometimes you just need a fresh pair of eyes. Thanks for spotting it!

2017-03-14 20:15:16 -0600 commented question LBP calcHist() Wrong

@Tetragramm Oh good eye, that's a definite problem. That being said, all the histograms seem to come out identical to the one above through imshow(), is there nothing else above that might be causing this? The problem you identified is one of accessing, not creating the hist.

2017-03-14 19:39:40 -0600 commented question LBP calcHist() Wrong

@Tetragramm Thanks for the hint, I've tried your tip but sadly the same outcome. When I iterate over all entries in hist.at<uchar>(i,j) it only shows entries of 0.

2017-03-14 16:16:28 -0600 asked a question LBP calcHist() Wrong

Hi everyone, I've written my own LBP method however it does not work. The outputted histogram of codes is 1 column that is identical for every inputted image. However the LBP map looks correct, so I think there is an error with one of the inputs to calcHist(). Are there any obvious errors? Thanks.

    Mat gray, lbpMap, hist;
    lbpMap.create(in.rows-2, in.cols-2, CV_8UC1);
    cvtColor(in, gray, CV_BGRA2GRAY);

    for (int i = 1; i < in.rows-1; i++)
      for (int j = 1; j < in.cols-1; j++){
        uchar thisPixel = gray.at<uchar>(i,j);
        uchar thisCode = 0;
        if (thisPixel > gray.at<uchar>(i-1,j-1))
          thisCode |= 1 << 7;
        if (thisPixel > gray.at<uchar>(i,j-1))
          thisCode |= 1 << 6;
        if (thisPixel > gray.at<uchar>(i+1,j-1))
          thisCode |= 1 << 5;
        if (thisPixel > gray.at<uchar>(i,j-1))
          thisCode |= 1 << 4;
        if (thisPixel > gray.at<uchar>(i+1,j-1))
          thisCode |= 1 << 3;
        if (thisPixel > gray.at<uchar>(i-1,j+1))
          thisCode |= 1 << 2;
        if (thisPixel > gray.at<uchar>(i,j+1))
          thisCode |= 1 << 1;
        if (thisPixel > gray.at<uchar>(i+1,j+1))
          thisCode += 1;

        //Add this string to histogram
        lbpMap.at<uchar>(i-1,j-1) = thisCode;
      }

    //After map built, get hist
    const int channelNo[] = { 0 };
    float range[] = { 0, 255 };
    const float *ranges[] = { range };
    int bins = 256;
    calcHist(&lbpMap, 1, channelNo, noArray(), hist, 1, &bins, ranges);

Here is the LBP map and hist after this code is run. Hist LBP

LBP contains values between 0 and 255 as expected, and hist contains just zeroes.

2017-03-04 03:00:44 -0600 received badge  Critic (source)
2017-03-03 15:45:51 -0600 commented answer Training SVM on HOG Crashes - Bad Memory Access

Hi, so I've stopped using addresses in general and this has not resolved my issue. I simply iterate over each item in the vector and copy it to the float array.

std::vector<float> thisHogVect = hog(trainingImages[i]);
      float thisHog[NUMVECTORS];
      for (int j = 0; j < thisHogVect.size(); j++){
        thisHog[j] = thisHogVect.at(j);
      }
      trainDataFloats[i] = thisHog;

However, if I fiddle with the NUMVECTORS constant, it does work if it is less than ~50. I think this is to do with the information being too large for the Mat data structure to handle 15000 floats per image. Do you agree?

2017-03-02 10:08:51 -0600 commented answer Hand mask has holes in it - Best way to deal with?

Just in addition to the above, I have tested out the above proposed solutions with the following code


  erode(in, out, *new Mat(cv::Size(6,6), CV_8U));
  dilate(out, out, *new Mat(cv::Size(6,6), CV_8U));
however this produces some problematic results. The fingers blur quite drastically and the holes do not get much better. I worry in particular about losing the intentional gaps between the fingers however in this case this was not problematic. Can you recommend any ways to improve this approach? I have updated my original answer to show the in and out when using this code. Many thanks.

2017-03-02 09:36:14 -0600 commented answer Hand mask has holes in it - Best way to deal with?

Thank you for the hints everyone. I would have thought that erosion & dilation would expand the hand evenly on all sides, so I would have some extra data on the outline of the hand. Previously I was doing

erode(lastPreprocessedROI, lastPreprocessedROI, Mat());
    dilate(lastPreprocessedROI, lastPreprocessedROI, Mat());
however this resulted in a pretty similar image. Do I need to modify the final argument as well to make it effective? And in response to @kbarni, is the closing just the erosion and dilation being applied in that order? The docs http://docs.opencv.org/2.4/doc/tutori... seem to suggest so

2017-03-01 11:44:33 -0600 commented answer Training SVM on HOG Crashes - Bad Memory Access

@berak thanks for the tip. I've changed it to return the vector of floats, and then take the address of that in the training method since the Mat needs to take an array not vector, however I don't think this is the problem as it yields the same result. The code looks like this now


      float* thisHog = &hog(trainingImages[i])[0];
      trainDataFloats[i] = thisHog;

2017-03-01 11:15:24 -0600 asked a question Training SVM on HOG Crashes - Bad Memory Access

Hi everyone, As the title says I am training my SVM on the HOG data from a HOGDescriptor as shown below. Train method:

  Ptr<ml::traindata> thisData;
  float **trainDataFloats = new float*[NUMIMGS];

  //For each image, get individual HOG element array and copy into TrainData
  for (int i = 0; i < NUMIMGS; i++){
    std::vector<float> thisHogVect = hog(trainingImages[i]);

    trainDataFloats[i] = new float[NUMVECTORS];
    for (int j = 0; j < NUMVECTORS; j++)
      trainDataFloats[i][j] = thisHogVect.at(j);
  }

  //Serialise the array into 1 contiguous block
  float trainDataOut[NUMIMGS*NUMVECTORS];
  for (int i = 0; i < NUMIMGS; i++)
    for (int j = 0; j < NUMVECTORS; j++)
      trainDataOut[i*NUMVECTORS+j] = trainDataFloats[i][j];
  Mat trainingMat(NUMIMGS, NUMVECTORS, CV_32FC1, trainDataOut);
  Mat labels(NUMIMGS, 1, CV_32FC1, labelsIn);
  thisData->create(trainingMat, ml::ROW_SAMPLE, labels);
  Mat trainSamples = thisData->getTrainSamples();
  imshow("", trainSamples);
  thisSVM->trainAuto(thisData);

HOG method:

std::vector<float> hog(Mat in)
  HOGDescriptor hog;
  std::vector<float> desc;
  std::vector<cv::point> locs;
  hog.compute(in, desc, *new cv::Size(32,32), *new cv::Size(0,0), locs);
  return desc;
}

There are only 20 images in the training set, 10 per class, so I am baffled that this is too much information for the Mat to hold, however 15000 floats per HOG is understandably large. Could anyone point me in the right direction as to how to capture the feature vectors from HOG without getting the bad access error that occurs? I highly suspect this is because there are too many values in the HOG output. Thanks.

EDIT: Changed the train method above to reflect current situation. Still getting 0x0 error on trainAuto() method, and also if I do thisData->getTrainSamples() it results in bad access too.

2017-03-01 05:43:39 -0600 asked a question Hand mask has holes in it - Best way to deal with?

Hi everyone, I have a thresholded binary mask from H-S back projection (applied back to the original image) as displayed below. I was wondering what the best image technique would be to solve the big holes. The holes are where the colour of the skin vary more. e.g. something like a convex hull may help, but I'm not exactly sure how to apply these. Any suggestions welcome.

Hand

Here is a photo of the in and output of the erosion and dilation suggestion: image description

2017-02-28 10:55:55 -0600 commented answer Load SVM from disk on iOS

@berak Thanks for the response. I've modified the code so that it uses this line. This appears to cause an error of the same nature still, however at a certain address rather than 0x0. The error is exc_bad_access address: 0x10bb5c000. And yes, Objective-C is a funny language that I'm not using out of choice ;)

2017-02-27 18:53:07 -0600 commented question Loading SVM results in crash FileStorage

@tomgekeerd Did you get to resolve this?

2017-02-27 18:35:22 -0600 asked a question Load SVM from disk on iOS

Hi everyone,

I am reading an SVM from my iOS app's document directory and it seemed to be working until I tried predicting something on it. The code is as follows:

    Ptr<ml::svm> SVMAVB;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,     YES);
    NSString *docs = [paths objectAtIndex:0];
    docs = [docs stringByAppendingPathComponent:@"Classifiers/"];

    NSString *vocabPath = [docs stringByAppendingPathComponent:@"SVMAVB.xml"];
    FileStorage fs([vocabPath UTF8String], FileStorage::READ);
    SVMAVB->load<ml::svm>(std::string([vocabPath UTF8String]));
    return SVMAVB->predict(features);

However after inspecting the code before predict runs, it turns out the object is null. This is surprising, I expected a warning or error! However the program proceeds to crash when executing predict, yielding a bad access to address 0x0. Could anyone provide any help on why this might not be loading?

I'm confident the SVM is not accurate (not sure why yet, I'll come to that later), but it does exist so I expected it to at least work! Thanks for the help.

2017-02-27 13:17:37 -0600 answered a question Imwrite() on iOS - Does it work?

The answer is yes! I found similar code on SO to this which did the job just fine:

 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex:0];
NSString *filePath = [directory stringByAppendingPathComponent:[NSString stringWithFormat:@"hand%f.jpg", CFAbsoluteTimeGetCurrent()]];
const char* filePathC = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];

const cv::String thisPath = (const cv::String)filePathC;

//Save image
imwrite(thisPath, capturedFrame);
2017-02-27 09:42:32 -0600 asked a question imwrite() saving different image

Hi,

I'm currently taking a photo on my iPad and saving it with imwrite(), however the saved image looks completely different. I believe it is to do with the resolution difference however I cannot be sure. One example is given below, where there are 2 hands in the original image, but only 1 in the saved one. Does anyone know why it might remove hands? Possibly to do with scaling the mat to the screen, but then why is the data removed when writing, not simply modified? Ignore the blueness, it's probably just a channel issue.

Original Saved

2017-02-24 06:06:07 -0600 asked a question Imwrite() on iOS - Does it work?

Hi everyone, I'm running this code on iOS

  imwrite("currentimg.jpg", capturedFrameOutImg);

And not getting any errors, however if I go into the photos app I don't see my Mat there. The Mat is a 3 channel image in the program but it doesn't seem to be saving. Is this functionality working on iOS or is this method not implemented? And if it is, where might I find my file?

Thanks!

2017-02-20 10:43:05 -0600 marked best answer Mat reshape not reducing channel number

Hi everyone, I get the error: error: (-215) mask.depth() == CV_8U && (mcn == 1 || mcn == cn) in function copyTo, when the following code runs. Why does reshape() not reduce the number of channels in mask to 1? I need a binary mask to find an object in the scene, however drawcontours() is giving me a grayscale 3 channel image, and my input image is 4 channels hence the error, but I thought reshape would fix this by reducing it to 1 channel. The printout of mcn states Mask has 3 channels.