I am trying to detect the nails from the image of hands and try to overlay detected nail area with colour. I have been trying different approaches using OpenCV , Vision but nothing worked out till date.
Below is the opencv method that I have been using..
+ (UIImage *)detectAndColorNailsInImage:(UIImage *)image withColor:(UIColor *)color {
cv::Mat inputMat;
UIImageToMat(image, inputMat);
// Convert the image to grayscale
cv::Mat grayscaleMat;
cv::cvtColor(inputMat, grayscaleMat, cv::COLOR_BGR2GRAY);
// Apply Gaussian blur to reduce noise
cv::Mat blurredMat;
cv::GaussianBlur(grayscaleMat, blurredMat, cv::Size(5, 5), 0);
// Apply thresholding to extract nails
cv::Mat thresholdMat;
cv::threshold(grayscaleMat, thresholdMat, 100, 255, cv::THRESH_TRIANGLE);
UIImage *outpqutImage = MatToUIImage(thresholdMat);
// Find contours
std::vector<std::vector<cv::Point>> contours;
cv::findContours(thresholdMat, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
// Draw contours on the original image
for (int i = 0; i < contours.size(); ++i) {
// Calculate contour area
double area = cv::contourArea(contours[i]);
// If the contour area is smaller than a threshold, it's likely not a nail
if (area < 100) {
continue;
}
// Draw contours with the specified color
cv::drawContours(inputMat, contours, i, cv::Scalar(255, 0, 0), 2);
}
UIImage *outputImage = MatToUIImage(inputMat);
return outputImage;}
And also I have been trying to use vision method as below
func vision(){
var rgbaIn = UIImage(named: "nail2.jpeg")!
guard let ciImage = CIImage(image: rgbaIn) else {
// Handle error
return
}
let request = VNDetectHumanHandPoseRequest()
let handler = VNImageRequestHandler(ciImage: ciImage)
do {
try handler.perform([request])
} catch {
print("Error: \(error)")
return
}
guard let observations = request.results else {
// No hand pose observations found
return
}
for observation in observations {
guard let handLandmarks = try? observation.recognizedPoints(.all) else {
continue
}
// Iterate through the recognized hand landmarks
for (jointName, points) in handLandmarks {
// Check if the joint corresponds to a finger tip
if jointName == .indexTip || jointName == .middleTip || jointName == .ringTip || jointName == .littleTip {
// Iterate through the detected points for this joint
rgbaIn = overlayColor(on: rgbaIn, at: points.location, color: UIColor.red)
print(rgbaIn)
}
}
// Use the overlayedImage for further processing or display
}
}
// Function to overlay color on the image at a specific position
func overlayColor(on image: UIImage, at position: CGPoint, color: UIColor) -> UIImage {
// Begin image context
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
defer { UIGraphicsEndImageContext() }
// Draw the original image
image.draw(at: .zero)
// Set the color
color.setFill()
// Create a CGRect with a small size (representing the nail)
let nailRect = CGRect(x: position.x - 5, y: position.y - 5, width: 50 , height: 50)
// Fill the CGRect with color
UIRectFill(nailRect)
// Get the overlaid image from the context
guard let overlayedImage = UIGraphicsGetImageFromCurrentImageContext() else {
return image
}
return overlayedImage
}
for the both above methods there is not suitable outcomes.! Any help or direction will be appreciated. Thank you.