冻鱼
不要说我们一无所有 我们要做天下的主人
iSTHMUS BLOG

无聊的作品-1

图像处理代码测试程序(基于QT5.9开发)

1.先来看看程序效果:

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621155389-image-1024x602.png
正常运行
https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621155541-image-1024x603.png
点击“加载图像”按钮弹出文件选择窗口
https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621155428-image-1024x602.png
在每次显示图像前,必须先加载图像,否则提示未加载

2.程序设计要求

  • 能够读取188*50左右的8位bmp灰度图
  • 能够显示图片
  • 有相关的错误提示

3.实现方法

QT封装了很多函数,可以参看QT的编程手册(见下图)

大概看来,需要引用文件操作相关的函数,也用到了massagebox以及用QLabel显示图像。

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621159195-image.png

因为只需要读bmp文件,为了方便(不会用QT的函数,仅仅用windows.h内已经定义好的数据类型,配合stdio.h内文件操作函数即可。

4.具体代码

bmp_read.h

#ifndef BMP_READ_H
#define BMP_READ_H

#include <windows.h>
#include "stdio.h"

#define CAMERA_H_MAX 200
#define CAMERA_W_MAX 400

extern int camera_raw_data[CAMERA_H_MAX][CAMERA_W_MAX];
extern int camera_real_w;
extern int camera_real_h;

extern int File_Read;   //

// 定义一个结构体来读取BMP的信息
typedef struct {
    // 定义文件头信息
    BITMAPFILEHEADER header;
    // 定义位图信息头
    BITMAPINFOHEADER info;
    // 定义彩色表
    RGBQUAD rgb[256];
    // 定义位图数据指针
    unsigned char* data;
} BMP;

extern BMP bmp;


void bmpRead(const char* bmpPath, BMP& bmp);
void bmpCells( BMP& bmp);

#endif // BMP_READ_H

bmp_read.cpp

#include "bmp_read.h"

int camera_raw_data[CAMERA_H_MAX][CAMERA_W_MAX];
int camera_real_w=0;
int camera_real_h=0;
int File_Read=0;   //图像已读入标志位

BMP bmp;

// 读图像函数
void bmpRead(const char* bmpPath, BMP& bmp) {
    // 以二进制的方式打开图片
    FILE* file = fopen(bmpPath, "rb");
    // 读取文件信息头
    fread(&bmp.header, sizeof(BITMAPFILEHEADER), 1, file);
    // 读取位图信息头
    fread(&bmp.info, sizeof(BITMAPINFOHEADER), 1, file);
    // 读取彩色表
    fread(&bmp.rgb, sizeof(RGBQUAD), 256, file);
    // 定义位图数据内存大小
    bmp.data = new unsigned char[bmp.info.biWidth * bmp.info.biHeight];
    // 读取元素的位图数据
    fread(bmp.data, sizeof(unsigned char), bmp.info.biWidth * bmp.info.biHeight, file);
    // 关闭图片
    fclose(file);

    camera_real_w=bmp.info.biWidth;
    camera_real_h=bmp.info.biHeight;
}

void bmpCells( BMP& bmp) {

    // 循环读取像素值
    for (int i = 0; i < bmp.info.biHeight; i++)
    {
        for (int j = 0; j < bmp.info.biWidth; j++)
        {
            // 获取循环到像元的像素值
            unsigned char pixel = bmp.data[j + i * bmp.info.biWidth];

            camera_raw_data[i][j] = pixel; //原始图像二维数组
        }

    }

}

主窗口类函数 (对应两个按键的槽函数)

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

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

void MainWindow::on_pushButton_loadimg_clicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,"选取图像文件","C:/", "images(*bmp)");//xx/xx/xx.xx
    QFileInfo base(fileName);
    QString basename = base.baseName(); //打开的文件文件名,xx。不包含文件后缀

    char path[50];  //Qstring 转char数组
    QByteArray ba = fileName.toLocal8Bit();
    memcpy(path,ba.data(),ba.size()+1);//加1是为了最后的终结符,否则转换回来的时候不知道什么时候截

    bmpRead(path,bmp);
    bmpCells(bmp);

    if(fileName!=0) File_Read=1;
    qDebug() << fileName;


}

void MainWindow::on_pushButton_showimg_clicked()
{
    if(File_Read)
    {
        unsigned char picbuf[camera_real_h][camera_real_w]={0};

        for(int i=0;i<camera_real_h;i++)    //复制数据
        {
            for(int j=0;j<camera_real_w;j++)
            {
                picbuf[i][j]=camera_raw_data[camera_real_h-i-1][j];
            }
        }

        //在此处调用图像处理函数,对picbuf数组处理

        //在此处调用图像处理函数,对picbuf数组处理
        int bytecount = ( camera_real_w * 8 + 31)/32 * 4;
        QByteArray imageByteArray = QByteArray( (const char*)picbuf,camera_real_h*bytecount);
        uchar*  transData = (unsigned char*)imageByteArray.data();
        QImage image = QImage(transData, camera_real_w, camera_real_h, QImage::Format_Indexed8);

        ui->label_img->setScaledContents(true);
        ui->label_img->setPixmap(QPixmap::fromImage(image));
    }
    else
    {
         QMessageBox::warning(NULL,"warning","尚未读入图片,请点击载入图片", QMessageBox::Ok);
    }

    File_Read=0;
}

可视化UI设计

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621159644-image-1024x523.png

5.打包程序

因为没事想把程序分发给好友试试,所以学习了一下打包方法。

QT默认使用动态链接库(DLL),所以直接生成的.exe是无法单独运行的,会提示丢失dll文件。

首先切换成release生成程序

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621159835-image.png

找到对应的程序

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621159875-image.png

我这个是已经打包好的,一般情况下QT Creator不会删除生成的.o文件以及过程中的.h文件,为了美观,先把这些没用的删掉,仅保留.exe文件

网上好像有很多打包方法,我使用QT自带mingw的打包程序

C:\Qt\Qt5.9.0\5.9\mingw53_32\bin\windeployqt

在QT的安装目录里找找,如果使用频率比较高,也可以添加进系统变量里,省的每次打路径。

命令很简单:

C:\Qt\Qt5.9.0\5.9\mingw53_32\bin\windeployqt IMG_DEBUG.exe

前面是windeployqt.exe 后面是你自己的.exe 不管用绝对路径或者相对路径,能找到就行

运行完可能还会提示缺少某些dll,直接到"qt_path"\mingw53_32\bin\下找到并复制进去就好了

就完了

6.总结

由于时间比较仓促,在复习近代史的摸鱼时间搞出来的。所以功能比较简陋,提示也不完全。甚至没有对可能的数组越界行为进行错误处理。不过作为一个小练习来说,基本上满足了任务需求,还是比较成功的。

https://blog.isthmus.tk:442/wp-content/uploads/2021/05/1621160689-image.png
#Define

#Define

文章作者

翻车鱼就是本人了

发表评论

textsms
account_circle
email

评论审核已启用。您的评论可能需要一段时间后才能被显示。

iSTHMUS BLOG

无聊的作品-1
基于QT的基础作品
扫描二维码继续阅读
2021-05-16