前言
在项目中,可能一些输入的图像要求是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 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"<
3、程序实现代码
transWidget.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
#include "opencv2/opencv.hpp"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
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 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"<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()<(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(mat.step), QImage::Format_RGB888 );
return image.rgbSwapped();
}
// 8-bit 1 channel
case CV_8UC1:
{
static QVector 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 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;iedt_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