Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

color replacement in image for iphone application

Basically i want to implement color replacement feature for my paint application. Below are original and expected output

Original: original

After changing wall color selected by user along with some threshold for replacement

desired output I have tried two approaches but could not got working as expected

Approach 1:
Queue-based Flood Fill algorithm for color replacement but with i got below output with terribly slow and wall shadow has not been preserved.

flood fill output

Approach 2: So i have tried to look at another option and found below post from SO How to change a particular color in an image?

but i could not understand logic and not sure about my code implementation from step 3.

Please find below code for each step wise with my understanding.

1) Convert the image from RGB to HSV using cvCvtColor (we only want to change the hue).

 IplImage *mainImage=[self CreateIplImageFromUIImage:[UIImage imageNamed:@"original.jpg"]];
 IplImage *hsvImage = cvCreateImage(cvGetSize(mainImage), IPL_DEPTH_8U, 3);
 IplImage *threshImage = cvCreateImage(cvGetSize(mainImage), IPL_DEPTH_8U, 3);
 cvCvtColor(mainImage,hsvImage,CV_RGB2HSV);

2) Isolate a color with cvThreshold specifying a certain tolerance (you want a range of colors, not one flat color).

cvThreshold(hsvImage, threshImage, 0, 100, CV_THRESH_BINARY);

3) Discard areas of color below a minimum size using a blob detection library like cvBlobsLib. This will get rid of dots of the similar color in the scene. Do i need to specify original image or thresold image?

CBlobResult blobs = CBlobResult(threshImage, NULL, 0);
blobs.Filter( blobs, B_EXCLUDE, CBlobGetArea(), B_LESS, 10);

4) Mask the color with cvInRangeS and use the resulting mask to apply the new hue.

Not sure about this function how it helps in color replacement and not able to understand arguments to be provided.

5) cvMerge the new image with the new hue with an image composed by the saturation and brightness channels that you saved in step one.

i understand that cvMerge will merge three channel of H S and V but how i can use output of above three steps.

so basically stuck with opencv implementation,

if possible then please guide me for opencv implemenation or any other solution to tryout.

like image 542
Jigar Parekh Avatar asked Feb 26 '13 05:02

Jigar Parekh


People also ask

Is there an app to change colors on a picture?

Step 1 — Download PhotoDirector — A Free Image Color Changer App. Available for iOS and Android devices, PhotoDirector is one of the best free image color changer apps on the market.

What app can change the color of something?

Color Changer-Coloring Editor 4+ Color changer allow you to colorize your photos and apply various splash effects.


1 Answers

Finally i am able to achieve some desired output using below javacv code and same ported to opencv too.

this solution has 2 problems

  1. don't have edge detection, i think using contours i can achieve it
  2. replaced color has flat hue and sat which should set based on source pixel hue sat difference but not sure how to achieve that. may be instead of cvSet using cvAddS

    IplImage image = cvLoadImage("sample.png");
    CvSize cvSize = cvGetSize(image);
    
    
    IplImage hsvImage = cvCreateImage(cvSize, image.depth(),image.nChannels());
    
    IplImage hChannel = cvCreateImage(cvSize, image.depth(), 1); 
            IplImage  sChannel = cvCreateImage(cvSize, image.depth(), 1); 
            IplImage  vChannel = cvCreateImage(cvSize, image.depth(), 1);
    cvSplit(hsvImage, hChannel, sChannel, vChannel, null);
    
    
    IplImage cvInRange = cvCreateImage(cvSize, image.depth(), 1);
    CvScalar source=new CvScalar(72/2,0.07*255,66,0); //source color to replace
    CvScalar from=getScaler(source,false);
    CvScalar to=getScaler(source, true);
    
    cvInRangeS(hsvImage, from , to, cvInRange);
    
    IplImage dest = cvCreateImage(cvSize, image.depth(), image.nChannels());
    
    IplImage temp = cvCreateImage(cvSize, IPL_DEPTH_8U, 2);
    cvMerge(hChannel, sChannel, null, null, temp);
    
    cvSet(temp, new CvScalar(45,255,0,0), cvInRange);// destination hue and sat
    cvSplit(temp, hChannel, sChannel, null, null);
    cvMerge(hChannel, sChannel, vChannel, null, dest);
    cvCvtColor(dest, dest, CV_HSV2BGR);
    cvSaveImage("output.png", dest);
    

method to for calculating threshold

    CvScalar getScaler(CvScalar seed,boolean plus){
    if(plus){
        return CV_RGB(seed.red()+(seed.red()*thresold),seed.green()+(seed.green()*thresold),seed.blue()+(seed.blue()*thresold));
    }else{
        return CV_RGB(seed.red()-(seed.red()*thresold),seed.green()-(seed.green()*thresold),seed.blue()-(seed.blue()*thresold));
    }
        }
like image 123
Jigar Parekh Avatar answered Sep 27 '22 19:09

Jigar Parekh