Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
715 views
in Technique[技术] by (71.8m points)

opencv - 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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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));
    }
        }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...