【问题标题】:color replacement in image for iphone applicationiPhone应用程序图像中的颜色替换
【发布时间】:2013-02-11 11:38:55
【问题描述】:

基本上我想为我的油漆应用程序实现颜色替换功能。 以下是原始和预期的输出

原文:

更改用户选择的墙壁颜色以及一些替换阈值后

我尝试了两种方法,但无法按预期工作

方法一:
Queue-based Flood Fill算法换色 但是由于我的输出速度非常慢,而且墙影没有被保留下来。

方法二: 所以我试图看看另一个选项,发现下面的帖子来自 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 这样的库。这将摆脱类似的点 场景中的颜色。 我需要指定原始图像还是阈值图像?

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

4) 用 cvInRangeS 屏蔽颜色并使用 生成的蒙版以应用新的色调。

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

5) cvMerge 新图像与 由饱和度和亮度组成的图像的新色调 您在第一步中保存的频道。

我知道 cvMerge 将合并 H S 和 V 的三个通道,但是我如何使用上述三个步骤的输出。

所以基本上坚持使用 opencv 实现,

如果可能,请指导我进行 opencv 实施或任何其他解决方案进行试用。

【问题讨论】:

  • 仅在步骤 4 中修改色调,然后在步骤 5 中使用原始饱和度是不够的。看看你的例子中的墙壁。它是灰色的。灰色的饱和度为零(或非常接近于零),这意味着色调没有效果。要将那面墙变成蓝色,您需要将饱和度设置为更接近 1(并且您需要设置色调)。
  • rob 你认为我的第二步和第三步正确吗?
  • @JigarParekh 我有同样的问题,但我必须实时完成(意味着在相机图像中)所以你可以指导如何做到这一点

标签: iphone opencv image-processing core-graphics quartz-core


【解决方案1】:

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

这个解决方案有两个问题

  1. 没有边缘检测,我认为使用轮廓我可以实现它
  2. 替换的颜色具有平坦的色调和饱和度,应根据来源设置 像素色调存在差异,但不确定如何实现。也许 用 cvAddS 代替 cvSet

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

【讨论】:

  • 您能否分享一下您为此功能所指的材料或教程?我也在研究类似的功能..找不到合适的东西:(
  • 如果你能分享会很棒
【解决方案2】:

我知道这个答案总有一天会对某人有用。 在 iOS 的 viewdidLoad() 覆盖方法中试试这个。 下面代码 sn-p 中的图像应该来自您的 UIImageView 种子也是固定的。您可以根据用户点击事件使其动态化。

 cv::Mat mask = cv::Mat::zeros(image.rows + 2, image.cols + 2, CV_8U);
 imageView.image = [self UIImageFromCVMat:image];
 cv::cvtColor(image, image, cv::COLOR_BGR2RGB);

  try {
    if(seed.x > 0 && seed.y > 0){
        cv::floodFill(image, mask, seed, cv::Scalar(50, 155, 20) ,0,        cv::Scalar(2,2, 2), cv::Scalar(2,2, 2), 8);
        cv::floodFill(image, mask, seed2, cv::Scalar(50, 155, 20) ,0, cv::Scalar(2,2, 2), cv::Scalar(2,2, 2), 8);
        cv::floodFill(image, mask, seed3, cv::Scalar(50, 155, 0) ,0, cv::Scalar(2,2, 2), cv::Scalar(2,2, 2), 8);

    }
} catch (Exception ex) {

}
cv::cvtColor(image, image, cv::COLOR_RGB2BGR);

self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.image = [self UIImageFromCVMat:image];

【讨论】:

    猜你喜欢
    • 2018-05-11
    • 2010-12-05
    • 2016-02-07
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多