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.
I used your mix way, but it's not work: the result is RGB color image, but losing many colors.
So I have a very simple way to convert, and it's successful
This code is in XCode:
lastImage = [firstImage CVMat];
cv::cvtColor(lastImage , lastImage , CV_RGBA2RGB);
It will convert lastImage to RGB color, with CV_8UC3 style.
Sorry because it's the first time I comment and I don't know how to format this.
A different approach might be creating a CV_8UC4 matrix and then splitting the channels, obtaining a bgr matrix, and an alpha matrix (discarded in this case):
cv::Mat CVMat(CGImageRef cgimage)
{
CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgimage);
CGFloat cols = CGImageGetWidth(cgimage);
CGFloat rows = CGImageGetHeight(cgimage);
cv::Mat rgba(rows, cols, CV_8UC4, Scalar(1,2,3,4)); // 8 bits per component, 4 channels
CGContextRef contextRef = CGBitmapContextCreate(rgba.data, // Pointer to backing data
cols, // Width of bitmap
rows, // Height of bitmap
8, // Bits per component
rgba.step[0], // Bytes per row
colorSpace, // Colorspace
kCGImageAlphaNoneSkipLast |
kCGBitmapByteOrderDefault); // Bitmap info flags
CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), cgimage);
CGContextRelease(contextRef);
Mat bgr( rgba.rows, rgba.cols, CV_8UC3 );
Mat alpha( rgba.rows, rgba.cols, CV_8UC1 );
Mat out[] = { bgr, alpha };
// rgba[0] -> bgr[2], rgba[1] -> bgr[1],
// rgba[2] -> bgr[0], rgba[3] -> alpha[0]
int from_to[] = { 0,2, 1,1, 2,0, 3,3 };
mixChannels( &rgba, 1, out, 2, from_to, 4 );
return bgr;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With