美文网首页
[OpenCV]关于图片通道转换的相关问题

[OpenCV]关于图片通道转换的相关问题

作者: 油焖微风 | 来源:发表于2016-11-30 23:13 被阅读1843次

    月初在研究OpenCV时发现一个问题就是很难解决,在stackoverflow上都很难找到解决的方案,问题是在调用 OpenCV的修复函数 inpaint(img, inpaintMask, inpainted, 3, INPAINT_TELEA); 报错,提示语为:“ OpenCV Error: Unsupported format or combination of formats (Only 8-bit 1-channel and 3-channel input/output images are supported) in cvInpaint, ” 错误原因为输入的inpaintMask代表的图像格式有问题,其通道数和位数不符合要求。

    一、背景知识

    RGB色彩模式 RGB色彩模式指的是红、绿、蓝(Red、Green、Blue)三个通道的颜色,而一般png图片是带有Alpha通道的(也就是俗称的透明度),也就是第四个通道。而单通道色彩模式实际上就是我们熟知的黑白图片。错误提示语中的“8-bit 1-channel”指的就是用8个bit(即1个字节)来表示单通道色阶的图片。而“8-bit 3-channel” 指的就是只有RGB三个通道的图片,没有Alpha通道,每个通道用8bit表示。

    二、解决方案

    也解决这个问题涉及到一个通道转到换和位数转换的问题。下面将分步介绍这个转换,这里我们采用OpenCV的iOS版本来阐述,只是开始获取图像数据时用到了Objective-C语言,其他时候都是调用C++/C语言,其转换部分是具有通用性的。

    Mat img0 = [[UIImage imageNamed:@"apple01"] cvMatRepresentationColor];//获取图像数据,用Mat类来表示
    

    第一步将其转换为结构体IplImage (IplImage , Mat 和CvMat 之间是可以相互转换的,都是代表图像数据的结构体或者类),根据其尺寸用cvCreateImage()创建能够存储3通道的图片结构体的内存区域,并用指针变量img3chan指向它

    IplImage img = img0;//可以直接赋值转换为结构体
    IplImage *img3chan = cvCreateImage(cvGetSize(&img),img.depth, 3);
    

    第二步是用cvCvtColor方法将img中的原始图片数据转化为RGB三通道的图片,并将图片数据保存到img3chan中。

    cvCvtColor(&img,img3chan,CV_RGBA2RGB);//CV_RGBA2RGB表示4通道转成3通道
    

    第三步是要完成位数的转换,以上几步只是完成通道数量的转换,同样我们需要用一个方法cvCreateMat()创建一个新的内存区域来作为容器来存放转换后的结果,最后用cvConvert()完成最终转换

        CvMat *cvMat = cvCreateMat(img.height, img.width, CV_8UC3);//创建容器区域
        cvConvert(img3chan, cvMat);
    

    以下是完整代码:

    - (void)handleInpaint{
        Mat img0 = [[UIImage imageNamed:@"apple01"] cvMatRepresentationColor];//
        IplImage img = img0;
        IplImage *img3chan = cvCreateImage(cvGetSize(&img),img.depth, 3);
        cvCvtColor(&img,img3chan,CV_RGBA2RGB);
        CvMat *cvMat = cvCreateMat(img.height, img.width, CV_8UC3);
        cvConvert(img3chan, cvMat);
        Mat img2 = Mat(cvMat);
        Mat inpaintMask = Mat::zeros(img2.size(), CV_8U);
        
        Vector<Mat> res = inpaintImage(img0,inpaintMask);
        if(res.size() >= 2){
            self.imgV.image = [UIImage imageFromCVMat:res[0]];
            self.imgV0.image = [UIImage imageFromCVMat:res[1]];
        }
    }
    
    Vector<Mat> inpaintImage(Mat&img0,Mat&inpaintMask){
        Vector<Mat>res_imgs;
        if(img0.empty()){
            return res_imgs;
        }
        Mat img = img0.clone();
        Mat inpainted;
        inpaint(img, inpaintMask, inpainted, 3, INPAINT_TELEA);
        res_imgs.push_back(inpainted);
        res_imgs.push_back(inpaintMask);
    //    imshow("修复后", inpainted);
    //    imshow("图像掩码",inpaintMask);
        return res_imgs;
    }
    

    相关文章

      网友评论

          本文标题:[OpenCV]关于图片通道转换的相关问题

          本文链接:https://www.haomeiwen.com/subject/nuotmttx.html