C++课设 简易图像处理系统

目录

前言

一、总体设计

1.1 主要功能

1.2 UML类图

二、代码实现

2.1 父类method

2.2 子类线性增强算法

2.3 gamma校正

2.4 管理类Manage.h

2.5 选择图像

2.6 保存和撤销图像

三、测试与分析

 四、完整代码

4.1 method.h

4.2 method.cpp

4.3 manage.h

4.4 manage.cpp

4.5 mainwindow.cpp

总结


前言

本次课设实现的简易图像处理主要采用了C++和OpenCV+Qt结合的方式,利用C++类的封装、多态、继承继承机制实现了对输入图像进行线性灰度变换、对数变换、gamma变换、拉普拉斯算子增强、直方图均衡化、rbg2gray、模糊图像增强七种处理方式,在线性变换和gamma变换的时候利用QMessageBox类实现弹窗功能,用户可以自己输入相关值对图像进行增强或对比度降低的操作,同时还利用栈的方式对图像操作进行撤销,最后将算法打包成了动态库,采用隐式调用.dll文件的方式实现了代码共享。


提示:以下是本篇文章正文内容,下面案例可供参考

一、总体设计

1.1 主要功能

(1)选择一张图像,对图像进行线性灰度变换、对数变换、gamma变换、拉普拉斯算子增强、直方图均衡化、rbg2gray、模糊图像增强处理;

(2)显示图像、将结果图像保存到文件;

(3)对图像所做操作进行撤销;

(4)利用对话框的形式显示算法简介。

系统实现:首先将算法抽象成一个类模板method,然后对类method针对数据类型<cv::Mat>进行特化,将成员函数runMethod设置为纯虚函数,接着将线性灰度变换、对数变换、gamma变换、拉普拉斯算子增强、直方图均衡化、rbg2gray六种算法类作为子类继承模板特化类,分别在其内部实现runMethod方法。同时定义一个管理类manage,对图像的保存撤销操作进行管理。

1.2 UML类图

二、代码实现

2.1 父类method

将图像增强算法抽象成一个类method,并将其写成一个模板类,然后针对Mat数据类型对类实现特化,编写setImage,getImage,imag_gray,isEmpty成员函数。

template<typename T>
class METHOD_EXPORT method
{
public:
    method();
    method(string str)   //带参构造函数
    {
        setImage(str);
    }
    virtual ~method()
    {
        cout<<"end of method!"<<endl;
    }
    void setImage(string str)
    {
        cv::Mat img = imread(str);   //cv::Mat是一种数据类型
        this->img = img;
    }
    cv::Mat getImage()
    {
        return this->img;
    }
    cv::Mat isEmpty()
    {
        if(img.empty())
        {
            cout<<"读入图片失败!"<<endl;
        }
    }
    virtual T runMethod()=0;        //纯虚函数,多态性
private:
    cv::Mat img;    //处理的图像
};

template <>
class method<cv::Mat>    //模板类特化
{
public:
    method();
    method(string str)
    {
        setImage(str);
    }
    virtual ~method()
    {
        cout<<"end of method!"<<endl;
    }
    void setImage(string str)
    {
        cv::Mat img = imread(str);   //cv::Mat是一种数据类型
        this->img = img;
    }
    cv::Mat getImage()
    {
        return this->img;
    }
    cv::Mat img_gray(cv::Mat s)    //彩色图转换为灰度图像
    {
        cv::Mat gray;
        if(!isEmpty())
        {
            cvtColor(s,gray,CV_BGR2GRAY);
            return gray;
        }
    }
    bool isEmpty()
    {
        if(img.empty())
        {
            cout<<"Loading false!"<<endl;
            return true;
        }
        else
            return false;
    }
    virtual Mat runMethod()=0;
private:
    cv::Mat img;
};

2.2 子类线性增强算法

线性灰度变换的公式是:g(x,y)=k*f(x,y)+b类LinearChange继承父类method,定义两个私有变量k,b,根据用户需要进行输入,然后重写父类method方法,对输入图像逐像元进行线性变换。

//图像的灰度线性变化
class LinearChange:public method<cv::Mat>
{
public:
    LinearChange();
    LinearChange(string str):method(str){};
    ~LinearChange()
    {
        cout<<"LInearChange is end!"<<endl;
    }
    cv::Mat runMethod();
    friend class MainWindow;
private:
    double k;         //线性变换方程:g(x,y)=k*f(x,y)+b
    double b;
};
Mat LinearChange::runMethod()
{
    Mat srcImg=this->getImage();
    if(srcImg.empty())
    {
        cout<<"读入图片失败"<<endl;
    }
    int RowsNum = srcImg.rows;
    int ColsNum = srcImg.cols;
    Mat dstImg(srcImg.size(),srcImg.type());
    //进行遍历图像像素,对每个像素进行相应的线性变换
    for(int i=0;i<RowsNum;i++)
    {
        for(int j=0;j<ColsNum;j++)
        {
            //c为遍历图像的三个通道
            for(int c=0;c<3;c++)
            {
                //imread读取到的Mat图像数据,都是用uchar类型的数据存储,Vec3b可以认为是vector<uchar,3>
                dstImg.at<Vec3b>(i,j)[c] = saturate_cast<uchar>
                        (k*(srcImg.at<Vec3b>(i,j)[c])+b);
            }
        }
    }
    return dstImg;
}

2.3 gamma校正

gamma变换的公式:s=c*f(x,y)^gamma,当gamma>1时,低灰度值区间的动态范围变小,高灰度值区间的动态范围变大,整体来说降低图像对比度,当0<gamma<1时,增强图像对比度。定义一个私有变量gamma,由用户自己输入,首先对0~255之间的每个整数执行一次预补偿操作,将其对应值存入一个预先建立的gamma校正查找表LUT,然后根据LUT对输入图像依次逐像元修改,最后返回结果图像。

//图像的gamma校正
class gammaTransform:public method<cv::Mat>
{
public:
    gammaTransform();
    gammaTransform(string str):method(str){};
    ~gammaTransform()
    {
        cout<<"gammaTransform is end!"<<endl;
    }
    cv::Mat runMethod();
    friend class MainWindow;
private:
    double gamma;  //归一化-->预补偿-->反归一化;s=pow(f,r)
};
Mat gammaTransform::runMethod()
{
    Mat srcImg=this->getImage();
    if(srcImg.empty())
    {
        cout<<"读入图片失败"<<endl;
    }
    //gamma校正查找表
    unsigned char LUT[256];
    for(int i = 0; i < 256; i++)
    {
        float f=(i+0.5f)/255;
        f=(float)pow(f,gamma);
        LUT[i] = saturate_cast<uchar>(f*255.0f-0.5f);
    }
    Mat imagegamma = srcImg.clone();
    //判断图像的通道数
    if(srcImg.channels()==1)   //灰度图像
    {
        //迭代器
        MatIterator_<uchar> iterator = imagegamma.begin<uchar>();
        MatIterator_<uchar> iteratorEnd = imagegamma.end<uchar>();
        for(;iterator!=iteratorEnd;iterator++)
        {
            *iterator = LUT[(*iterator)];
        }
    }
    else
    {
        //输入通道为三通道时,需要对每个通道分别进行变换
        MatIterator_<Vec3b> iterator = imagegamma.begin<Vec3b>();
        MatIterator_<Vec3b> iteratorEnd = imagegamma.end<Vec3b>();
        //通过查表进行转换
        for(;iterator!=iteratorEnd;iterator++)
        {
            (*iterator)[0] = LUT[((*iterator)[0])];
            (*iterator)[1] = LUT[((*iterator)[1])];
            (*iterator)[2] = LUT[((*iterator)[2])];
        }
    }
    return imagegamma;
}

2.4 管理类Manage.h

定义一个保存图像的栈,将每次操作的图像入栈,删除之后出栈,stack_Number用来计数栈中元素,sign作为标识,以便撤销处理,如果sign == false且stack_Number == 0,则弹出误操作提示框,如果sian==true且stack_Number == 0 则说明已撤销至初始状态。

class manage
{
public:
    string imagePath;            //图片路径
    stack<cv::Mat> imageStack;   //存储图片的栈
    //int stack_Number = 0;        //初始化栈中元素为空
    manage():imagePath("none"){};
    ~manage();
    void giveImage_path(string path);
    void saveImage(string path);
    void pushStack(Mat image);      //将执行操作的图片入栈
    cv::Mat undoImage();   //撤销
};
#include "manage.h"
#include<iostream>
using namespace std;
manage::~manage()
{

}
void manage::giveImage_path(string path)
{
     this->imagePath = path;
}
void manage::saveImage(string path)
{
    cv::Mat element;
    element=this->imageStack.top();
    imwrite(path,element);
}
void manage::pushStack(Mat image) //操作图像入栈
{
    this->imageStack.push(image);
    //this->stack_Number++;
}
cv::Mat manage::undoImage() //撤销
{
    cv::Mat dstImg;
    if(this->imageStack.size()==1)
    {
        dstImg = this->imageStack.top();
        this->imageStack.pop();
        //this->stack_Number--;

        return dstImg;
    }
    else if(this->imageStack.size()>1)
    {
        this->imageStack.pop();
        //this->stack_Number--;
  • 6
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值