I tried to solve your problem with the idea that you need a method applicable to similar images. So, I wrote a small algorithm that read the pixels of the image and detect when there's a sudden change in intensity(0-255) and blur the subregion. Particularly, I create an imaginary rectangle(1x9 pixel) which I iterate through the image. For each movement of the rectangle I iterate IN it vertically(that is, read 9 vertical pixels) and check for sudden delta in intensity(in this case 30) and blur that area with a normal blur. But before doing all this, I apply a threshold to highlight the hair. The result is not exactly what you asked but hey, I enjoyed myself :-).
Here's the code:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image;
image = imread("hand.jpg", IMREAD_GRAYSCALE);
if (image.data==NULL)
cout << "Img not found" << endl;
namedWindow("hand", WINDOW_AUTOSIZE);
Mat orig = image.clone();
threshold(image, image, 180, 255, THRESH_BINARY);
int height = 8;
for(int x=0;x<image.cols;x++)
for (int y = height / 2; y < image.rows - height / 2; y++)
{
int whiteToBlack = 0, blackToWhite = 0;
for (int rectY = y - height / 2; rectY < y + height / 2 - 1; rectY++)
if (image.at<uchar>(rectY, x) > image.at<uchar>(rectY + 1, x) && image.at<uchar>(rectY, x) - image.at<uchar>(rectY + 1, x) > 30)
whiteToBlack++;
else if (image.at<uchar>(rectY, x) < image.at<uchar>(rectY + 1, x) && image.at<uchar>(rectY + 1, x) - image.at<uchar>(rectY, x) > 30)
blackToWhite++;
if (whiteToBlack > 0 && blackToWhite > 0)
for (int rectY = y - height / 4; rectY < y + height / 4 - 1; rectY++)
blur(orig(Rect(x, y - height / 2, 4, height + 1)), orig(Rect(x, y - height / 2, 4, height + 1)),Size(3,3));
}
imshow("hand", orig);
waitKey(0);
}
The result:
Easier way to do this is
grabcut
. Can be found in OpenCV' s folder.