[OpenCV学习笔记]Qt+OpenCV实现图像灰度反转、对数变换和伽马变换

目录

1、介绍

1.1 灰度反转

灰度反转是一种线性变换,是将某个范围的灰度值映射到另一个范围内,一般是通过灰度的对调,突出想要查看的灰度区间。

S = L − 1 − r ( r ⊂ [ 0 , L − 1 ] ) S = L -1-r (r \subset [0,L-1]) S=L−1−r(r⊂[0,L−1])

比如在以下胸片图像中提取白色絮状形状,在黑色背景下看的不太明显,就可以使用灰度反转增强图像的可视化效果。

复制代码
output_img = input_img.clone();
for(int i = 0; i < input_img.rows; i++)
{
    for(int j = 0; j < input_img.cols; j++)
    {
        output_img.at<uchar>(i, j) = 255 - input_img.at<uchar>(i, j)
    }
}

1.2 图像对数变换

对数变换可以将图像中低灰度值的部分进行提升,显示出低灰度部分的特征,对高灰度值部分进行抑制,减少高灰度值部分的细节,从而实现增项图像俺不细节,优化图像的对比度。
S = c log ⁡ ( 1 + r ) S=c\log(1+r) S=clog(1+r)

其原理就是,对数曲线在像素值低的区域斜率大,在像素值高的地方斜率小。

对数变换后图像的灰度值可能会超出0~255的区间,所以在对数变换后要进行归一化处理,将图像灰度值调节回0-255的区间。

复制代码
	Mat LogarithmImg = grayImg.clone();
    for(int i=0;i<grayImg.rows;i++)
    {
        for(int j=0;j<grayImg.cols;j++)
        {
            LogarithmImg.at<uchar>(i,j) = 6*log((double)grayImg.at<uchar>(i,j) + 1);
        }
    }
    normalize(LogarithmImg, LogarithmImg, 0, 255,NORM_MINMAX);
    convertScaleAbs(LogarithmImg,LogarithmImg);

1.3 图像伽马变换

图像的伽马变换其实就是通过非线性变换将图像中较暗区域的灰度值进行增强,对较亮区域的灰度值进行抑制,从而获得图像比较好的细节特征。
s = c r γ ( r ∈ [ 0 , 1 ] ) s=cr^\gamma (r\in[0, 1]) s=crγ(r∈[0,1])

r为灰度的输入值,c为灰度缩放系数,伽马因子控制整个变换的缩放程度。

复制代码
    Mat gammaImg = grayImg.clone();
    for(int i=0;i<grayImg.rows;i++)
    {
        for(int j=0;j<grayImg.cols;j++)
        {
            gammaImg.at<uchar>(i,j) = 6*pow((double)grayImg.at<uchar>(i,j), 0.5);
        }
    }
    normalize(gammaImg, gammaImg, 0, 255,NORM_MINMAX);
    convertScaleAbs(gammaImg,gammaImg);

2、效果图

使用lena图进行灰度反转、对数变换、伽马变化测试,在Qt上实现加载和变换。

3、代码实现

widget.h

复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "opencv2/opencv.hpp"
#include <QResizeEvent>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

using namespace cv;
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_btn_loadPic_clicked();

    void on_btn_InversionTrans_clicked();

    void on_btn_logarithmTrans_clicked();

    void on_btn_gammaTrans_clicked();

    void on_btn_resetPic_clicked();

private:
    Ui::Widget *ui;
    // 灰度图像
    Mat grayImg;
    // Mat图像类型转换为QImage
    QImage cvMat2QImage(const cv::Mat &mat);
};
#endif // WIDGET_H

widget.cpp

复制代码
#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("OpenCV图像变换");
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_btn_loadPic_clicked()
{
    Mat Img = imread("lena.png");
    cvtColor(Img, grayImg, COLOR_BGR2GRAY);

    QImage qImg_Gray = cvMat2QImage(grayImg);
    ui->lbl_grayPic->setPixmap(QPixmap::fromImage(qImg_Gray.scaled(ui->lbl_grayPic->size())));
}


void Widget::on_btn_InversionTrans_clicked()
{
    Mat InversionImg = grayImg.clone();
    for(int i=0;i<grayImg.rows;i++)
    {
        for(int j=0;j<grayImg.cols;j++)
        {
            InversionImg.at<uchar>(i,j) = 255 - grayImg.at<uchar>(i,j);
        }
    }
    QImage qImg_Inversion = cvMat2QImage(InversionImg);
    ui->lbl_InversionPic->setPixmap(QPixmap::fromImage(qImg_Inversion.scaled(ui->lbl_InversionPic->size())));
}


void Widget::on_btn_logarithmTrans_clicked()
{
    Mat LogarithmImg = grayImg.clone();
    for(int i=0;i<grayImg.rows;i++)
    {
        for(int j=0;j<grayImg.cols;j++)
        {
            LogarithmImg.at<uchar>(i,j) = 6*log((double)grayImg.at<uchar>(i,j) + 1);
        }
    }
    normalize(LogarithmImg, LogarithmImg, 0, 255,NORM_MINMAX);
    convertScaleAbs(LogarithmImg,LogarithmImg);
    QImage qImg_Logarithm = cvMat2QImage(LogarithmImg);
    ui->lbl_LogPic->setPixmap(QPixmap::fromImage(qImg_Logarithm.scaled(ui->lbl_LogPic->size())));
}


void Widget::on_btn_gammaTrans_clicked()
{
    Mat gammaImg = grayImg.clone();
    for(int i=0;i<grayImg.rows;i++)
    {
        for(int j=0;j<grayImg.cols;j++)
        {
            gammaImg.at<uchar>(i,j) = 6*pow((double)grayImg.at<uchar>(i,j), 0.5);
        }
    }
    normalize(gammaImg, gammaImg, 0, 255,NORM_MINMAX);
    convertScaleAbs(gammaImg,gammaImg);
    QImage qImg_Gamma = cvMat2QImage(gammaImg);
    ui->lbl_GammaPic->setPixmap(QPixmap::fromImage(qImg_Gamma.scaled(ui->lbl_GammaPic->size())));
}


void Widget::on_btn_resetPic_clicked()
{
    ui->lbl_grayPic->clear();
    ui->lbl_InversionPic->clear();
    ui->lbl_LogPic->clear();
    ui->lbl_GammaPic->clear();
}

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() )
        {
            sColorTable.resize( 256 );
            for ( int i = 0; i < 256; ++i )
            {
                sColorTable[i] = qRgb( i, i, i );
            }
        }
        QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(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();
}

4、源码展示

本小例程的代码放到我的开源gitte项目里,欢迎一起学习交流,也希望能收获你的小星星。
项目源码GrayTrans

相关推荐
肥or胖10 小时前
【FFmpeg 快速入门】本地播放器 项目
开发语言·qt·ffmpeg·音视频
海绵波波10711 小时前
opencv、torch、torchvision、tensorflow的区别
人工智能·opencv·tensorflow
小灰灰搞电子16 小时前
Qt Quick 粒子系统详解
开发语言·qt
顾随16 小时前
(三)OpenCV——图像形态学
图像处理·人工智能·python·opencv·计算机视觉
暴躁茹18 小时前
Qt 将触摸事件转换为鼠标事件(Qt4和Qt5及以上版本)
开发语言·qt·计算机外设
大专生学编程20 小时前
QT简介和QT环境搭建
c++·qt
feiyangqingyun20 小时前
Qt/C++开发监控GB28181系统/视频点播没有ssrc问题的处理/兼容各种设备和应用场景需求
c++·qt·gb28181
小堃学编程1 天前
QT跨平台应用程序开发框架(10)—— Qt窗口
开发语言·qt
轩宇^_^1 天前
Qt CMake 学习文档
数据库·qt·学习
小徐不徐说1 天前
QT技巧之快速搭建串口收发平台
开发语言·c++·qt·串口·软件构建·个人开发·通信