I’m working on resizing the nose on a facial image using OpenCV in Objective-C++ for iOS. The goal is to elongate or shorten the nose, but my current implementation only modifies a cropped area, which is then overlaid back onto the original image rather than adjusting the nose size directly on the face. Here is the snippet from my OpenCVWrapper.mm
:
+ (UIImage *)makeNoseLongerInImage:(UIImage *)image withFactor:(int)scaleFactor {
cv::Mat mat;
[image convertToMat:&mat :false];
NSString *path = [[NSBundle mainBundle] pathForResource:@"haarcascade_frontalface_default" ofType:@"xml"];
cv::CascadeClassifier face_cascade;
if (!face_cascade.load([path UTF8String])) {
NSLog(@"Failed to load face cascade from path: %@", path);
return image;
}
std::vector<cv::Rect> faces;
face_cascade.detectMultiScale(mat, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
for (const cv::Rect& face : faces) {
cv::Rect noseArea(
std::max(0, face.x + static_cast<int>(face.width * 0.25)),
std::max(0, face.y + static_cast<int>(face.height * 0.60)),
std::min(mat.cols - face.x, static_cast<int>(face.width * 0.50)),
std::min(mat.rows - face.y, static_cast<int>(face.height * 0.12))
);
if (noseArea.width == 0 || noseArea.height == 0) {
NSLog(@"nose area computed with zero width or height.");
continue;
}
cv::Mat noseRegion = mat(noseArea);
int newHeight = std::max(1, static_cast<int>(noseRegion.rows * scaleFactor / 100.0));
cv::Mat resizednoseRegion;
cv::resize(noseRegion, resizednoseRegion, cv::Size(noseRegion.cols, newHeight), 0, 0, cv::INTER_LINEAR);
NSLog(@"Original nose region: (%d, %d), Resized: (%d, %d)", noseRegion.cols, noseRegion.rows, resizednoseRegion.cols, resizednoseRegion.rows);
// Place the resized nose region back into the original mat
if (!resizednoseRegion.empty() && resizednoseRegion.cols == noseRegion.cols && resizednoseRegion.rows == newHeight) {
// Update the noseArea to match the resized dimensions
cv::Rect newnoseArea = noseArea;
newnoseArea.height = newHeight; // Update height to match resized region
resizednoseRegion.copyTo(mat(newnoseArea));
} else {
NSLog(@"Mismatch in dimensions after resize or empty resized region.");
}
}
return MatToUIImage(mat);
}