iPhoneを使用して3Dグラスを顔にマッピングしようとしています。私は次のOpenCVの目の検出を使用しています。ただし、目の検出はあまり堅牢ではありません。顔を少し回したり、目が少し細くなったときにカメラを見下ろしたりすると、目の検出が機能しません。正面の顔でも半分のフレームしか検出しません。特定のパラメーターを微調整すると、画像の前処理に役立つという多くの場所を読みました。しかし、私は正しい組み合わせを得ることができません。以下は、私が使用している前処理とパラメーターです。誰かがより良いパラメーターを提案/共有できる場合は、助けてください。ありがとう
pixelBuffer
-imageからグレースケール画像を取得しています。次にprocessFrame
呼び出されます:
if (format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) {
// For grayscale mode, the luminance channel of the YUV data is used
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
void *baseaddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
cv::Mat mat(videoRect.size.height, videoRect.size.width, CV_8UC1, baseaddress, 0);
[self processFrame:mat videoRect:videoRect videoOrientation:videoOrientation];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
else if (format == kCVPixelFormatType_32BGRA) {
// For color mode a 4-channel cv::Mat is created from the BGRA data
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
void *baseaddress = CVPixelBufferGetBaseAddress(pixelBuffer);
cv::Mat mat(videoRect.size.height, videoRect.size.width, CV_8UC4, baseaddress, 0);
[self processFrame:mat videoRect:videoRect videoOrientation:videoOrientation];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
else {
NSLog(@"Unsupported video format");
}
分類子の初期化:
NSString * const kFaceCascadeFilename = @"haarcascade_frontalface_alt2";
NSString * const kEyesCascadeFilename = @"haarcascade_eye";
processFrame: 検出を行う
- (void)processFrame:(cv::Mat &)mat videoRect:(CGRect)rect videoOrientation:(AVCaptureVideoOrientation)videOrientation
{
// Shrink video frame to 320X240
cv::resize(mat, mat, cv::Size(), 0.5f, 0.5f, CV_INTER_LINEAR);
rect.size.width /= 2.0f;
rect.size.height /= 2.0f;
// Rotate video frame by 90deg to portrait by combining a transpose and a flip
// Note that AVCaptureVideoDataOutput connection does NOT support hardware-accelerated
// rotation and mirroring via videoOrientation and setVideoMirrored properties so we
// need to do the rotation in software here.
cv::transpose(mat, mat);
CGFloat temp = rect.size.width;
rect.size.width = rect.size.height;
rect.size.height = temp;
if (videOrientation == AVCaptureVideoOrientationLandscapeRight)
{
// flip around y axis for back camera
cv::flip(mat, mat, 1);
}
else {
// Front camera output needs to be mirrored to match preview layer so no flip is required here
}
videOrientation = AVCaptureVideoOrientationPortrait;
// Detect faces
std::vector<cv::Rect> faces;
std::vector<cv::Rect> eyes;
_faceCascade.detectMultiScale(mat, faces, 1.1, 2, 0 |CV_HAAR_SCALE_IMAGE, cv::Size(30, 30));
// We will usually have only one face in frame
if (faces.size() >0){
cv::Mat faceROI = mat(faces.front());
_eyesCascade.detectMultiScale( faceROI, eyes, 1.15, 3.0, 0 , cv::Size(30, 30));
}
// Dispatch updating of face markers to main queue
dispatch_sync(dispatch_get_main_queue(), ^{
[self displayFaces:faces eyes:eyes
forVideoRect:rect
videoOrientation:videOrientation];
});
}