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

转载 2016年05月31日 16:18:16

转自:分享用于学习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

微信分享示例代码

new title function shareText(){ var data = {}; da...
  • haozhenming
  • haozhenming
  • 2016年12月13日 15:33
  • 1804

Android集成微信分享的要点及源码示例

如今,社会化分享成了App必不可少的一个功能,而其中最重要的莫过于微信分享,由于微信庞大的用户群及活跃度,因此我们的App往往都需要集成微信分享,微信开放平台也提供了相应的分享SDK。鉴于看到很多人说...
  • u014738140
  • u014738140
  • 2015年03月10日 16:59
  • 1805

C/C++ 开源库及示例代码

C/C++ 开源库及示例代码= == 说明 =本页面汇总俺收集的各种 C 和 C++ 的开源代码库,不定期更新。如果你发现本页面的开源库有错漏之处,非常欢迎给俺提供反馈——有 GitHub 帐号的同学...
  • x356982611
  • x356982611
  • 2016年11月16日 16:15
  • 5042

Caffe系列(12)利用caffe.proto自定义自己的网络

利用caffe.proto自定义自己的网络 利用caffeproto自定义自己的网络 先不急让我们来看一下caffeproto里面都是些什么让我们把caffeproto用起后记 ...
  • u014696921
  • u014696921
  • 2016年09月17日 22:11
  • 796

C++ 高级语法学习与总结(代码实例)

http://www.cnblogs.com/gongxijun/p/4375791.html C++ 高级语法学习与总结(代码实例)     C++11增加了许多的特性,...
  • zdy0_2004
  • zdy0_2004
  • 2015年04月01日 19:30
  • 1096

【源代码】一键分享各个社交平台_android

[代码] [Java]代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
  • xb12369
  • xb12369
  • 2014年11月20日 16:05
  • 4542

C/C++ 开源库及示例代码

来源:https://github.com/programthink/opensource/blob/master/libs/cpp.wiki C/C++ 开源库及示例代码 ...
  • u011430225
  • u011430225
  • 2015年08月26日 09:35
  • 4625

使用深度学习Caffe框架的C++接口进行物体分类

实现目标: 1、加载一张图片,然后显示图片的类别 2、加载一个文件夹,分类所有文件夹类的图片,把所有图片保存到其所属类别最大的那个文件夹里。小于一定权重值的图片不移动。 3、实现工程project...
  • HYY0228
  • HYY0228
  • 2017年03月27日 19:30
  • 936

Caffe深度学习框架作者贾扬清online内容分享II

caffe算法与结构
  • paomojing
  • paomojing
  • 2016年07月20日 18:26
  • 1120

社会化分享功能百度分享代码示例

手机端APP:社会化分享组件ShareSDK你值得拥有友盟社会化分享组件ShareSDK for Android开发文档http://wiki.mob.com/Android_%E5%BF%AB%E9...
  • jethai
  • jethai
  • 2016年08月28日 14:02
  • 667
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【分享用于学习C++图像处理的代码示例】框架
举报原因:
原因补充:

(最多只允许输入30个字)