2013-02-26 110 views
5

基本上我想为我的绘画应用程序实现颜色替换功能。 下面是原始的和预期的输出iPhone应用程序的图像中的颜色替换

原文: original

用户与某个阈值以及选择更换改变墙壁的颜色

desired output 我已经尝试了两种方法,但不能得到预期运行后

方法1:
Queue-based Flood Fill算法颜色替换 但我得到低于输出非常缓慢,墙影未得到保存。

flood fill output

方法2: 所以我必须想看看另一种选择和SO How to change a particular color in an image?

发现下面的文章,但我无法理解我的,从代码实现的逻辑,而不是确定第3步。

请根据我的理解,找到以下代码,了解每个步骤。

1)使用cvCvtColor将图像从RGB转换为HSV(我们只想更改色调 )。

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)隔离与cvThreshold指定 一定公差的颜色(要一定范围的颜色,而不是一个平面彩色)。的最小尺寸以下的颜色

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

3)弃区域使用斑点检测 库等cvBlobsLib。这将消除场景中类似 颜色的点。 我是否需要指定原始图像或thresold图像?

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

4)面膜与cvInRangeS颜色和使用 所得掩模以应用新的色调。

不确定这个函数如何帮助颜色替换,并且不能理解要提供的参数。

5)cv将新图像与 新色调合成一个图像,并在第1步中保存的饱和度和亮度 通道组成。

我明白,cvMerge会合并H S和V三个通道,但我如何使用以上三个步骤的输出。

所以基本上坚持了OpenCV的实现,

如果可能的话,请指导我对OpenCV的实行或任何其他解决方案试训。

+1

是 代替CVSET这是不够的修改在步骤4中只是色相,然后使用原始饱和度在第5步。看看你的例子中的墙。它是灰色的。灰色的饱和度为零(或非常接近于零),这意味着色调没有影响。要将墙壁变成蓝色,您需要将饱和度设置为接近1(*和*您需要设置色调)。 – 2013-02-26 05:38:59

+0

rob你认为我的第二步和第三步是正确的吗? – 2013-02-26 15:13:58

+0

@JigarParekh我有同样的问题,但我必须做到实时(在相机图像的手段),所以你可以指导如何做到这一点 – Prabhakar 2015-06-18 07:58:39

回答

3

最后,我能够使用下面的javacv代码实现一些所需的输出,并且同样移植到opencv。

该解决方案具有2个问题

  1. 没有边缘检测,我想使用轮廓我可以实现它
  2. 更换颜色具有平坦的色调和饱和应该设置基于源 像素的色调,其坐在差异,但不知道如何实现。可以使用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); 
    

方法用于计算阈

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

很好的答案... +1 – jagdish 2014-06-25 07:44:43

+1

你可以请分享你指的是什么材料或教程此功能 ?我也在研究类似的功能..找不到合适的东西:( – Shailesh 2014-12-15 06:21:12

+0

如果你可以分享的话会很棒 – woohoou 2016-12-13 06:58:35