I am trying to use the people detection feature 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 statement:
OpenCV error: approval 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 that makes sense because I am transmitting the CV_8UC4 image.
So, I figured that I should create cvmat with such characteristics. Now I have these 2 methods. which allow me to get gray or color cvmats (CV_8UC1 / CV_8UC4)
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 shades of gray:
-(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 do this 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 to create an 8GB compatible CGBitmapContext? (I assume 8UC3 means 8 bits per pixel with RGB channels)
Thanks.
PD: Image conversion code belongs to Robin Summerhill.