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

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

  1. 深度学习(图像处理)代码库

    为大家整理的代码资源库,收集了大量深度学习项目图像处理领域的代码链接.包括图像识别,图像生成,看图说话等等方向的代码,所有代码均按照所属技术领域建立索引,以便大家查阅使用. 2.1 图像生成  2.1 ...

  2. 主动学习简单教程及代码示例

    本文是这篇文章的(翻译)简化版. 本文代码地址 已经不止一次有人说代码地址打不开,但是每次我都打得开..这里放个阿里云的地址吧Active_Learning_Tutorial.ipynb.需要的去阿里 ...

  3. 强化学习(Sarsa与q-learning)代码示例

    一.Sarsa算法 Sarsa算法是on-policy的,行为策略是什么,目标策略就是什么,即优化的是他实际执行的策略,所以使用Sarsa算法的agent在探索时显得有点"胆小". ...

  4. Selenium学习_常用场景代码示例

    启动Chrome浏览器,并链接到Baidu IWebDriver chromeSession = new ChromeDriver(@"C:\realUserTool\resource\ch ...

  5. 大数据学习之Spark-core常用代码示例

    一.查看分区表 packagecom.shujia.spark.core importorg.apache.spark.rdd.RDD importorg.apache.spark.{SparkCon ...

  6. 7个使用PyTorch的技巧,含在线代码示例!网友:我连第一个都不知道?!

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 丰色 发自 凹非寺 量子位 报道 | 公众号 QbitAI 大家在使 ...

  7. python判别性别的代码_python如何实现性别识别 python实现性别识别代码示例

    python如何实现性别识别?本篇文章小编给大家分享一下python实现性别识别代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. 使用keras ...

  8. java五子棋棋盘_java绘制五子棋棋盘代码示例

    本篇文章小编给大家分享一下java绘制五子棋棋盘代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. 代码如下: import javax.imag ...

  9. python pexpect模块详解_python Pexpect模块如何使用 python Pexpect模块使用代码示例

    python Pexpect模块如何使用?本篇文章小编给大家分享一下python Pexpect模块使用代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以 ...

  10. python表情代码_python如何实现表情识别 python实现表情识别代码示例

    python如何实现表情识别?本篇文章小编给大家分享一下python实现表情识别代码示例,文章代码介绍的很详细,小编觉得挺不错的,现在分享给大家供大家参考,有需要的小伙伴们可以来看看. 表情识别 表情 ...

最新文章

  1. 创业公司反内卷行为大赏
  2. 武汉科技大学ACM:1002: 华科版C语言程序设计教程(第二版)例题6.6
  3. php打开并填充表单,php – 创建一个’机器人’来填充带有一些页面的表单
  4. asp 之 让实体中字段类型为DateTime的字段仅仅显示日期不显示时间
  5. 编写一个java打印心程序_java – ?同时打印心脏符号
  6. 数三角形(51Nod-2497)
  7. QT:MainWindow初始化列表解释
  8. python编程能有什么用_揭秘python都能做什么?
  9. gdalwarp:变形工具
  10. c语言gc,使用C++制作GC Server过程详解
  11. 实用的 Python —— base64
  12. 2021 编程语言排行榜出炉
  13. openshift operator 介绍
  14. Sky Computing:利用空间异构分布式计算特性加速联邦学习
  15. tomcat用c语言开发服务,apache tomcat是什么语言开发的
  16. 数据可视化怎么选择图表
  17. 计算机课程基础常用,计算机基础课程实用标准
  18. 用电销外呼系统的回拨线路真的不会封号吗?
  19. 跑路不止、“幽灵所”激增,加密货币交易行业加速洗牌 |链捕手
  20. 海丝一号-中国-2020

热门文章

  1. 一个基于protobuf的极简RPC
  2. MySQL的Binlog与Redolog
  3. printf_s与printf的异同
  4. .net excel循环插数据_[PaperReading]MEMC-Net 运动估计和运动补偿网络
  5. 安卓背景音乐开关_奢华大屏背景音乐系统-圣巴赫S820,行业典范!
  6. k8s部署应用nginx
  7. springboot自定义异常(全局捕获)
  8. 前端入职后很痛苦_NGW前端新技术赛场:Serverless SSR 技术内幕
  9. Vagrant:将装在C盘的虚拟机移动到别的目录
  10. Python:将从chrome中复制的cookies转换为字典的函数