前言
在我的项目中,可能一些输出的图像要求是RGB的图像格式,然而手边只有单通道的黑白相机进行采图,这时就须要将8位的单通道图像转换成24位的三通道图像,个别都是应用3个8位图像叠加成三通道图像。
1、OpenCV实现单通道转三通道
首先创立一个CV_8UC3的三通道图像,图像大小尺寸与单通道图像尺寸统一,而后将3份单通道图像叠加交融填入刚创立的三通道图像。
Mat Widget::convertTo3Channels(const cv::Mat& binImg){ cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3); std::vector<cv::Mat> channels; for (int i=0;i<3;i++) { channels.push_back(binImg); } cv::merge(channels,three_channel); return three_channel;}
2、判断图像通道数进行转换
这里先判断图像是否是单通道还是四通道,如果是四通道,将图像间接转换成三通道。如果是单通道应用下面程序转换成三通道
//判断输出图像的通道数 if(curMatImg.type() == CV_8UC4) { cvtColor(curMatImg,curMatImg,COLOR_RGBA2RGB); qDebug()<<"width"<<curMatImg.cols<<curMatImg.rows; } else if(curMatImg.type() == CV_8UC1) { curMatImg = convertTo3Channels(curMatImg); } else { qDebug()<<"Img is 3 Channels"; }
3、程序实现代码
transWidget.h
#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QSettings>#include <QFileInfo>#include <QFileDialog>#include <QDebug>#include <QMessageBox>#include "opencv2/opencv.hpp"namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private slots: void on_btn_trans_clicked(); void on_btn_close_clicked(); void on_btn_OpenFile_clicked(); void on_btn_NextPic_clicked(); void on_btn_LoadPic_clicked(); void on_btn_SaveImgPath_clicked();private: Ui::Widget *ui; QImage curImg; //文件夹中图像数量 int PicNum; //文件夹以后加载图像下标 int CurPicIndex=0; //批量加载图像文件夹的门路 QString file_path; //以后图像名称 QString CurfileName; //图像名称缓存 QMap<int,QString> PicNameInfo; //保留文件夹文件数量 int saveFile_Num; //Mat转换QImage QImage cvMat2QImage(const cv::Mat& mat); //QImage转换Mat cv::Mat QImage2Mat(QImage image); //图像转换到三通道 cv::Mat convertTo3Channels(const cv::Mat& binImg); void checkCurPicIndex();};#endif // WIDGET_H
transWidget.cpp
#pragma execution_character_set("utf-8")#include "widget.h"#include "ui_widget.h"using namespace cv;Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); ui->btn_NextPic->setEnabled(false);}Widget::~Widget(){ delete ui;}void Widget::on_btn_trans_clicked(){ //保留图像 if(ui->edt_ImgSavePath->text().isEmpty()) { QMessageBox::critical(NULL, "critical", "未指定保留文件夹,请设置!"); return; } else { Mat curMatImg = QImage2Mat(curImg); //判断输出图像是不是8位灰度图像 if(curMatImg.type() == CV_8UC4) { cvtColor(curMatImg,curMatImg,COLOR_RGBA2RGB); qDebug()<<"width"<<curMatImg.cols<<curMatImg.rows; } else if(curMatImg.type() == CV_8UC1) { curMatImg = convertTo3Channels(curMatImg); } else { qDebug()<<"Img is 3 Channels"; } QImage QimgTrans = cvMat2QImage(curMatImg); QImage ShowTranImg = QimgTrans.scaled(ui->lbl_RGBImg->size(),Qt::KeepAspectRatio); ui->lbl_RGBImg->setPixmap(QPixmap::fromImage(ShowTranImg)); QString SaveFilePath = ui->edt_ImgSavePath->text() + "/trans_" + QString::number(saveFile_Num) +".bmp"; QimgTrans.save(SaveFilePath); saveFile_Num++; }}Mat Widget::QImage2Mat(QImage image){ Mat cvMat; qDebug()<<image.format(); switch(image.format()) { case QImage::Format_ARGB32: case QImage::Format_RGB32: cvMat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(cvMat, cvMat, COLOR_BGRA2BGR); break; case QImage::Format_ARGB32_Premultiplied: cvMat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_RGB888: cvMat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(cvMat, cvMat, COLOR_BGR2RGB); break; case QImage::Format_Indexed8: cvMat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_Grayscale8: cvMat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; } return cvMat;}QImage Widget::cvMat2QImage(const cv::Mat &mat){ switch ( mat.type() ) { // 8-bit 4 channel case CV_8UC4: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB32 ); return image; } // 8-bit 3 channel case CV_8UC3: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB888 ); return image.rgbSwapped(); } // 8-bit 1 channel case CV_8UC1: { static QVector<QRgb> sColorTable; // only create our color table once if ( sColorTable.isEmpty() ) { for ( int i = 0; i < 256; ++i ) sColorTable.push_back( qRgb( i, i, i ) ); } QImage image( mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8 ); image.setColorTable( sColorTable ); return image; } default: qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels()); qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type(); break; } return QImage();}Mat Widget::convertTo3Channels(const cv::Mat& binImg){ cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3); std::vector<cv::Mat> channels; for (int i=0;i<3;i++) { channels.push_back(binImg); } // cv::merge() cv::merge(channels,three_channel); return three_channel;}void Widget::on_btn_close_clicked(){ close();}void Widget::on_btn_OpenFile_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); file_path = QFileDialog::getExistingDirectory(this, "请抉择文件夹门路...", lastPath); if(file_path.isEmpty()) { QMessageBox::warning(this,"Warning","未抉择文件夹,请从新抉择文件夹!"); return; } else { PicNameInfo.clear(); CurPicIndex = 0; QDir dir(file_path); //改文件夹曾经判断是否存在,保障以后必然存在 QStringList filter; filter<<"*.bmp"<<"*.jpg"<<"*.png"; QFileInfoList list = dir.entryInfoList(filter, QDir::Files); //获取文件信息列表 if(!list.isEmpty()) { // qDebug() << list.count();//输入图片名 for(int i=0;i<list.count();i++){ QFileInfo fileInfo = list.at(i); qDebug() << fileInfo.fileName();//输入图片名 PicNameInfo.insert(i,fileInfo.fileName()); } CurfileName = PicNameInfo.value(0); QString picPathShow = file_path + "/" + PicNameInfo.value(0); ui->edt_ImgFolderPath->setText(picPathShow); curImg.load(picPathShow); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); checkCurPicIndex(); } else { QMessageBox::warning(this,"Warning","该文件夹为空,请从新抉择文件夹!"); return; } } }void Widget::on_btn_NextPic_clicked(){ CurPicIndex++; CurfileName = PicNameInfo.value(CurPicIndex); QString curPicPath = file_path + "/" + PicNameInfo.value(CurPicIndex); ui->edt_ImgFolderPath->setText(curPicPath); curImg.load(curPicPath); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); checkCurPicIndex();}void Widget::on_btn_LoadPic_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); QFileInfo file; QString PicPath =QFileDialog::getOpenFileName(this,QString::fromLocal8Bit("抉择图像文件"),lastPath,"图像文件 (*.bmp *.jpg *.png)"); if(PicPath.isEmpty()) { return; } else { file = QFileInfo(PicPath); // CurfileName = file.fileName(); //获取文件名 // qDebug() << CurfileName;//输入图片名 qDebug()<<"加载图像胜利"; // QImage img(PicPath); curImg.load(PicPath); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); // ui->graphicsView->fitInView(ImageItem); }}void Widget::checkCurPicIndex(){ if(PicNameInfo.size()>1) { if(CurPicIndex == 0) { // ui->btnPreviousPic->setEnabled(false); ui->btn_NextPic->setEnabled(true); } else if(CurPicIndex == PicNameInfo.count()-1) { ui->btn_NextPic->setEnabled(false); // ui->btnPreviousPic->setEnabled(true); } else { // ui->btnPreviousPic->setEnabled(true); ui->btn_NextPic->setEnabled(true); } } }void Widget::on_btn_SaveImgPath_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); QString save_path = QFileDialog::getExistingDirectory(this, "请抉择文件夹门路...", lastPath); ui->edt_ImgSavePath->setText(save_path); QDir *dir = new QDir(save_path); QStringList filter; QFileInfoList fileInfoList = dir->entryInfoList(filter); saveFile_Num = fileInfoList.count()-2;}
4、实现成果
5、源码学习
最初附上源码学习,能够在仓库按需自取,仓库中代码仅供学习应用。
GrayTo3channel