关闭

【分享用于学习C++图像处理的代码示例】框架

标签: 图像处理框架
241人阅读 评论(0) 收藏 举报
分类:

转自:分享用于学习C++图像处理的代码示例

为了便于学习图像处理并研究图像算法,

俺写了一个适合初学者学习的小小框架。

 

麻雀虽小五脏俱全。

 

采用的加解码库:stb_image

官方:http://nothings.org/

 

stb_image.h用于解析图片格式:

JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC

stb_image_write.h用于保存图片格式:

PNG, TGA, BMP, HDR

 

附带处理耗时计算,示例演示了一个简单的反色处理算法,并简单注释了一下部分逻辑。

 

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <iostream>
#include <algorithm>
 
#include <cstdint>
#include <numeric>
#include <math.h>
#include <io.h>
 
//使用stbImage http://nothings.org/
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
 
//如果是Windows的话,调用系统API ShellExecuteA打开图片
#if defined(_MSC_VER)
#include <windows.h>
#define USE_SHELL_OPEN
#endif
 
//是否使用OMP方式计时
#define USE_OMP 0
 
#if  USE_OMP
#include <omp.h>
auto const epoch = omp_get_wtime();
double now() {
    return omp_get_wtime() - epoch;
};
#else
#include <chrono>
auto const epoch = std::chrono::steady_clock::now();
double now() {
    return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - epoch).count() / 1000.0;
};
#endif
 
//计时函数
template<typename FN>
double bench(const FN &fn) {
    auto took = -now();
    return (fn(), took + now());
}
 
//存储当前传入文件位置的变量
std::string m_curFilePath;
 
//加载图片
void loadImage(const char* filename, unsigned char*& Output, int  &Width, int  &Height, int &Channels)
{
    Output = stbi_load(filename, &Width, &Height, &Channels, 0);
}
//保存图片
void saveImage(const char* filename, int  Width, int  Height, int Channels, unsigned char* Output, bool open = true)
{
    std::string saveFile = m_curFilePath;
    saveFile += filename;
    //保存为png,也可以调用stbi_write_bmp 保存为bmp
    stbi_write_png(saveFile.c_str(), Width, Height, Channels, Output, 0);
 
#ifdef USE_SHELL_OPEN
    if (open)
        ShellExecuteA(NULL, "open", saveFile.c_str(), NULL, NULL, SW_SHOW);
#else
    //其他平台暂不实现
#endif
}
 
//取当前传入的文件位置
void getCurrentFilePath(const char* filePath, std::string& curFilePath)
{
    char drive[_MAX_DRIVE];
    char dir[_MAX_DIR];
    char fname[_MAX_FNAME];
    char ext[_MAX_EXT];
    curFilePath.clear();
    _splitpath_s(filePath, drive, dir, fname, ext);
    curFilePath += drive;
    curFilePath += dir;
    curFilePath += fname;
    curFilePath += "_";
}
 
//算法处理,这里以一个反色作为例子
void processImage(unsigned char* Input, unsigned char* Output, unsigned int  Width, unsigned int  Height, unsigned int Channels)
{
    int WidthStep = Width*Channels;
    if (Channels == 1)
    {
        for (unsigned int Y = 0; Y < Height; Y++)
        {
            unsigned char*     pOutput = Output + (Y * WidthStep);
            unsigned char*     pInput = Input + (Y * WidthStep);
            for (unsigned int X = 0; X < Width; X++)
            {
                pOutput[0] = 255 - pInput[0];
 
                //下一个像素点
                pInput += Channels;
                pOutput += Channels;
            }
        }
    }
    else    if (Channels == 3 || Channels == 4)
    {
        for (unsigned int Y = 0; Y < Height; Y++)
        {
            unsigned char*     pOutput = Output + (Y * WidthStep);
            unsigned char*     pInput = Input + (Y * WidthStep);
            for (unsigned int X = 0; X < Width; X++)
            {
                pOutput[0] = 255 - pInput[0];
                pOutput[1] = 255 - pInput[1];
                pOutput[2] = 255 - pInput[2];
                //通道数为4时,不处理A通道反色(pOutput[3] = 255 - pInput[3];)
                //下一个像素点
                pInput += Channels;
                pOutput += Channels;
            }
        }
    }
 
}
 
//本人博客:http://tntmonks.cnblogs.com/转载请注明出处.
 
int main(int argc, char **argv) {
 
    std::cout << "Image Processing " << std::endl;
    std::cout << "Demo By Gaozhihan (Build 2016-03-22)" << std::endl;
    std::cout << "支持解析如下图片格式:" << std::endl;
    std::cout << "JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC" << std::endl;
 
    //检查参数是否正确
    if (argc < 2)
    {
        std::cout << "参数错误。" << std::endl;
        std::cout << "请拖放文件到可执行文件上,或使用命令行:imageProc.exe 图片" << std::endl;
        std::cout << "例如: imageProc.exe d:\\image.jpg" << std::endl;
 
        return 0;
    }
 
    std::string szfile = argv[1];
    //检查输入的文件是否存在
    if (_access(szfile.c_str(), 0) == -1)
    {
        std::cout << "输入的文件不存在,参数错误!" << std::endl;
    }
 
    getCurrentFilePath(szfile.c_str(), m_curFilePath);
 
    int Width = 0;        //图片宽度
    int Height = 0;        //图片高度
    int Channels = 0;    //图片通道数
    unsigned char* inputImage = NULL;    //输入图片指针
 
    double nLoadTime = bench([&]{
        //加载图片
        loadImage(szfile.c_str(), inputImage, Width, Height, Channels);
    });
    std::cout << " 加载耗时: " << int(nLoadTime * 1000) << " 毫秒" << std::endl;
    if ((Channels != 0) && (Width != 0) && (Height != 0))
    {
        //分配与载入同等内存用于处理后输出结果
        unsigned char* outputImg = (unsigned char*)STBI_MALLOC(Width*Channels*Height*sizeof(unsigned char));
        if (inputImage) {
            //如果图片加载成功,则将内容复制给输出内存,方便处理
            memcpy(outputImg, inputImage, Width*Channels*Height);
        }
        else     {
            std::cout << " 加载文件: \n" << szfile.c_str() << " 失败!" << std::endl;
        }
 
        double nProcessTime = bench([&]{
            //处理算法
            processImage(inputImage, outputImg, Width, Height, Channels);
        });
        std::cout << " 处理耗时: " << int(nProcessTime * 1000) << " 毫秒" << std::endl;
 
        //保存处理后的图片
        double nSaveTime = bench([&]{
            saveImage("_done.png", Width, Height, Channels, outputImg);
        });
        std::cout << " 保存耗时: " << int(nSaveTime * 1000) << " 毫秒" << std::endl;
 
        //释放占用的内存
        if (outputImg)
        {
            STBI_FREE(outputImg);
            outputImg = NULL;
        }
 
        if (inputImage)
        {
            STBI_FREE(inputImage);
            inputImage = NULL;
        }
    }
    else
    {
        std::cout << " 加载文件: \n" << szfile.c_str() << " 失败!" << std::endl;
    }
 
    getchar();
    std::cout << "按任意键退出程序 \n" << std::endl;
    return 0;
}

  

示例具体流程为:

加载图片->算法处理->保存图片->打开保存图片(仅Windows)

并对 加载,处理,保存 这三个环节都进行了耗时计算并输出。

 

示例代码下载:

http://files.cnblogs.com/files/tntmonks/imageProcDemo.zip

 

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是: 
gaozhihan@vip.qq.com

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:358167次
    • 积分:6455
    • 等级:
    • 排名:第3907名
    • 原创:255篇
    • 转载:234篇
    • 译文:6篇
    • 评论:35条
    最新评论