I am trying to use the people detection function in OpenCV:
cv::HOGDescriptor hog;
hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());
std::vector<cv::Rect> found;
hog.detectMultiScale(noMask, found, 0.2, cv::Size(8,8), cv::Size(16,16), 1.05, 2);
But I get the following assertion:
OpenCV Error: Assertion failed (img.type() == CV_8U || img.type() ==
CV_8UC3) in computeGradient, file
/Users/robin/Projects/OpenCVForiPhone/opencv/opencv/modules/objdetect/src/hog.cpp,
line 174
And it makes sense because I am passing a CV_8UC4 image.
So I guessed I should create a cvmat with this characteristics. Right now I have these 2 methods. which allow me to get gray or color cvmats (CV_8UC1/CV_8UC4)
For Color:
-(cv::Mat)CVMat
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGFloat cols = self.size.width;
CGFloat rows = self.size.height;
cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage);
CGContextRelease(contextRef);
return cvMat;
}
For Grayscale:
-(cv::Mat)CVGrayscaleMat
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGFloat cols = self.size.width;
CGFloat rows = self.size.height;
cv::Mat cvMat = cv::Mat(rows, cols, CV_8UC1); // 8 bits per component, 1 channel
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNone |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
return cvMat;
}
And this is my guess to make it 3 channels:
-(cv::Mat)CVMat3Channels
{
//CGColorSpaceRef colorSpace = CGImageGetColorSpace(self.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat cols = self.size.width;
CGFloat rows = self.size.height;
cv::Mat cvMat(rows, cols, CV_8UC3); // 8 bits per component, 3 channels
CGContextRef contextRef = CGBitmapContextCreate(cvMat.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
cvMat.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), self.CGImage);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
return cvMat;
}
But I get the following error:
<Error>: CGBitmapContextCreate: invalid data bytes/row: should be
at least 9792 for 8 integer bits/component, 3 components,
kCGImageAlphaNoneSkipLast.
<Error>: CGContextDrawImage: invalid context 0x0
So my question is, What is the correct way of creating a 8UC3 compatible CGBitmapContext?
(I assume the 8UC3 means 8 bits per pixel with RGB channels)
Thank you.
PD: The image transformation code is from Robin Summerhill.
You are correctly creating a 3-channel image by using
CV_8UC3. SinceCGBitmapContextCreateexpects9792bytes/row, that means there should be3264columns (of 3-channel pixels). If I run the following code,it outputs
9792as is required byCGBitmapContextCreate. Can you tell whatcvMat.step[0]is returning in your code? It looks correct, but maybe something else is going on.Also, note OpenCV natively stores data in BGR format if you’re getting the image data from OpenCV functions like
imreadetc. So, if the color looks weird, pay attention to that.