[OpenCV]關于圖片通道轉換的相關問題

月初在研究OpenCV時發(fā)現(xiàn)一個問題就是很難解決,在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個字節(jié))來表示單通道色階的圖片。而“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()創(chuàng)建能夠存儲3通道的圖片結構體的內存區(qū)域,并用指針變量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()創(chuàng)建一個新的內存區(qū)域來作為容器來存放轉換后的結果,最后用cvConvert()完成最終轉換

    CvMat *cvMat = cvCreateMat(img.height, img.width, CV_8UC3);//創(chuàng)建容器區(qū)域
    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;
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容