掩膜的操作与图像模糊类似,背后都是数学的卷积计算:
掩膜操作实现图像对比度调整:
红色是中心像素,从上到下,从左到右对每个像素做同样的处理操作,得到最终结果就是对比度提高之后的输出图像Mat对象。
代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPushButton>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
srcImage = imread("F:\\visual studio\\Image\\lion.jpg");
if (srcImage.empty())//!src.data
{
cout << "couldn't load image..\n" << endl;
}
LabelShowImage(srcImage,ui->src);
//建立信号槽,点击convert按钮后,对源图像进行掩膜操作, 然后显示处理后的图像.
connect(ui->pbconvert,&QPushButton::clicked,this,&MainWindow::convert);
}
//将Mat对象在label中显示 BGR->RGB
void MainWindow::LabelShowImage(const Mat & Image,QLabel * label)
{
Mat newImage;
cv::cvtColor(Image, newImage, CV_BGR2RGBA);//转换格式
QImage img = QImage(newImage.data, newImage.cols, newImage.rows, newImage.step, QImage::Format_RGBA8888);
//QImage scaleimg = img.scaled(label->size(),Qt::KeepAspectRatio, Qt::SmoothTransformation);
label->setPixmap(QPixmap::fromImage(img));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::convert()
{
dstImage = Mat::zeros(srcImage.size(),srcImage.type());
//掩膜操作
// int cols=srcImage.cols*srcImage.channels();
// int rows=srcImage.rows;
// int offset=srcImage.channels();
// for(int row=1;row<rows-1;row++)
// {
// const uchar* current = srcImage.ptr<uchar>(row);
// const uchar* previous = srcImage.ptr<uchar>(row-1);
// const uchar* next = srcImage.ptr<uchar>(row+1);
// uchar* output = dstImage.ptr<uchar>(row);
// for(int col=offset;col<cols-offset;col++)
// {
// output[col]=saturate_cast<uchar>(5*current[col]-(current[col-offset]+current[col+offset]+previous[col]+next[col]));
// }
// }
//直接利用Api
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
filter2D(srcImage,dstImage,srcImage.depth(),kernel);
LabelShowImage(dstImage,ui->dst);
}
代码解释:
读取一张图片至SrcImage后,在QT的Label控件中显示,但是Mat存储的形式为BGR,QImage存储形式为RGB,需要使用 cv::cvtColor(Image, newImage, CV_BGR2RGBA)转换格式并存入newImage,newImage.data为uchar* 类型,指向newImage存储的数据。
QImage(uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
可以根据此构造函数生成QImage,并使用setPixmap(QPixmap::fromImage())在label上显示图片。
output[col]=saturate_cast<uchar>(5*current[col]-(current[col-offset]+current[col+offset]+previous[col]+next[col])),这一步中要注意:
1.offset值的设置,因为这是3通道的图像。
2.saturate_cast<uchar>:这个函数的功能是确保RGB值得范围在0~255之间
saturate_cast<uchar>(-100),返回 0。
saturate_cast<uchar>(288),返回255
saturate_cast<uchar>(100),返回100
掩膜操作既可以通过对Mat像素点访问和修改完成,也可以在设置kernel后,直接调用filter2D,与上述效果几乎相同,但它对边界进行了一定处理。
Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
filter2D(srcImage,dstImage,srcImage.depth(),kernel);
计算过程如下:
anchor表示kernel的锚点,一般选择的都是中心点。
程序运行效果如下: