用于iphone应用的图像颜色替换

问题描述 投票:6回答:2

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

原版的:

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

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

方法1: 用于颜色替换的Queue-based Flood Fill算法,但是我得到了低于输出的非常缓慢的墙壁阴影并没有得到保留。

方法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)使用blob检测库(如cvBlobsLib)丢弃低于最小大小的颜色区域。这将消除场景中相似颜色的点。我是否需要指定原始图像或背景图像?

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

4)使用cvInRangeS掩盖颜色并使用生成的蒙版应用新色调。

不确定这个函数它如何帮助更换颜色并且无法理解要提供的参数。

5)cv使用新色调对新图像进行处理,图像由在第一步中保存的饱和度和亮度通道组成。

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

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

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

iphone opencv image-processing core-graphics quartz-core
2个回答
4
投票

最后,我能够使用下面的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));
    }
        }

0
投票

我知道这个答案总有一天对某人有用。在你的视图中试试这个用于iOS的viewdidLoad()覆盖方法。下面的代码片段中的图像应该来自您的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];
© www.soinside.com 2019 - 2024. All rights reserved.