图像处理卷积算法实现
时间:2022-05-10
本文章向大家介绍图像处理卷积算法实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
今天心血来潮,想把传统的卷积算法实现一份不采用各种加速方式,仅优化算法逻辑的纯净版本。
写完发现性能还可以,特发出来分享之,若有博友在此基础上,进行了再次优化,那就更赞了。
算法很简单:
inline unsigned char Clamp2Byte(int n) {
return (((255 - n) >> 31) | (n & ~(n >> 31)));
}
void Convolution2D(unsigned char * data, unsigned int width, unsigned int height, unsigned int channels, int * filter, unsigned char filterW, unsigned char cfactor, unsigned char bias) {
unsigned char * tmpData = (unsigned char * ) malloc(width * height * channels);
int factor = 256 / cfactor;
int halfW = filterW / 2;
if (channels == 3 || channels == 4) {
for (int y = 0; y < height; y++) {
int y1 = y - halfW + height;
for (int x = 0; x < width; x++) {
int x1 = x - halfW + width;
int r = 0;
int g = 0;
int b = 0;
unsigned int p = (y * width + x) * channels;
for (unsigned int fx = 0; fx < filterW; fx++) {
int dx = (x1 + fx) % width;
int fidx = fx * (filterW);
for (unsigned int fy = 0; fy < filterW; fy++) {
int pos = (((y1 + fy) % height) * width + dx) * channels;
int * pfilter = & filter[fidx + (fy)];
r += data[pos] * ( * pfilter);
g += data[pos + 1] * ( * pfilter);
b += data[pos + 2] * ( * pfilter);
}
}
tmpData[p] = Clamp2Byte(((factor * r) >> 8) + bias);
tmpData[p + 1] = Clamp2Byte(((factor * g) >> 8) + bias);
tmpData[p + 2] = Clamp2Byte(((factor * b) >> 8) + bias);
}
}
} else
if (channels == 1) {
for (int y = 0; y < height; y++) {
int y1 = y - halfW + height;
for (int x = 0; x < width; x++) {
int r = 0;
unsigned int p = (y * width + x);
int x1 = x - halfW + width;
for (unsigned int fx = 0; fx < filterW; fx++) {
int dx = (x1 + fx) % width;
int fidx = fx * (filterW);
for (unsigned int fy = 0; fy < filterW; fy++) {
int pos = (((y1 + fy) % height) * width + dx);
int szfilter = filter[fidx + (fy)];
r += data[pos] * szfilter;
}
}
tmpData[p] = Clamp2Byte(((factor * r) >> 8) + bias);
}
}
}
memcpy(data, tmpData, width * height * channels);
free(tmpData);
}
调用例子:
例子
//模糊
int Blurfilter[25] = {
0, 0, 1, 0, 0,
0, 1, 1, 1, 0,
1, 1, 1, 1, 1,
0, 1, 1, 1, 0,
0, 0, 1, 0, 0,
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, Blurfilter, 5, 13, 0);
// 运动模糊
int MotionBlurfilter[81] = {
1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, MotionBlurfilter, 9, 9, 0);
//边缘探测1
int edges1filter[25] = {
-1, 0, 0, 0, 0,
0, -2, 0, 0, 0,
0, 0, 6, 0, 0,
0, 0, 0, -2, 0,
0, 0, 0, 0, -1,
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, edges1filter, 5, 1, 0);
//边缘探测2
int edges2filter[9] = {
-1, -1, -1, -1, 8, -1, -1, -1, -1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, edges2filter, 3, 1, 0);
//锐化1
int sharpen1filter[9] = {
-1, -1, -1, -1, 9, -1, -1, -1, -1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, sharpen1filter, 3, 1, 0);
//锐化2
int sharpen2filter[25] = {
-1, -1, -1, -1, -1, -1, 2, 2, 2, -1, -1, 2, 8, 2, -1, -1, 2, 2, 2, -1, -1, -1, -1, -1, -1,
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, sharpen2filter, 5, 8, 0);
//锐化3
int sharpen3filter[9] = {
1, 1, 1,
1, -7, 1,
1, 1, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, sharpen3filter, 3, 1, 0);
// 浮雕1
int Embossfilter[9] = {
-1, -1, 0, -1, 0, 1,
0, 1, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, Embossfilter, 3, 1, 128);
// 浮雕2
int emboss2filter[25] = {
-1, -1, -1, -1, 0, -1, -1, -1, 0, 1, -1, -1, 0, 1, 1, -1, 0, 1, 1, 1,
0, 1, 1, 1, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, emboss2filter, 5, 1, 128);
// 均值模糊1
int meanfilter[9] = {
1, 1, 1,
1, 1, 1,
1, 1, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, meanfilter, 3, 9, 0);
// 均值模糊2
int mean2filter[81] = {
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, mean2filter, 9, 81, 0);
博主在一张大小为960x1280的图片,进行了边缘探测卷积核的处理,在博主机子上耗时是100毫秒。
//边缘探测1
int edges1filter[25] = {
-1, 0, 0, 0, 0,
0, -2, 0, 0, 0,
0, 0, 6, 0, 0,
0, 0, 0, -2, 0,
0, 0, 0, 0, -1,
};
Convolution2D(imgData, imgWidth, imgHeight, imgChannels, edges1filter, 5, 1, 0);
效果图:
其他相关资料,见各种百科网站。
关键词:卷积(英语:Convolution)
- HDUOJ---2546 饭卡
- 假期前的数据库检查脚本之主备关系(r11笔记第46天)
- HDUOJ----1003 Max Sum
- HDUOJ--Bone Collector
- HDUOJ--1058HangOver
- 免插件实现WordPress的Sitemap功能
- HDUOJ--1865 1string
- Golang语言延迟函数defer用法分析
- HDUOJ---大菲波数
- HDUOJ Children’s Queue
- HDUOJ----1250 Hat's Fibonacci
- HDUOJ---1133(卡特兰数扩展)Buy the Ticket
- HDUOJ--2079选课时间(题目已修改,注意读题)
- HDUOJ---2082
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- .net core 利用中间件处理常见的网站功能 包括 session、routers、重定向、重写和文件下载
- 蓝牙芯片----BK3431开发笔记------RW stack中添加自定义服务教程(4)
- 图像简单处理
- 蓝牙---BLE GATT介绍
- Access数据库密码破解 C#
- 没啥用,更换注册表信息使webbrower选择适合的版本
- linux下分割和合并压缩包
- 编译.net .net Core程序 代码,仅做备份
- js删除数组对象中符合条件的数据
- .net core webapi jwt 更为清爽的认证 ,续期很简单(2)
- 手把手教你写一个windows服务 【基于.net】 附实用小工具{注册服务/开启服务/停止服务/删除服务}
- 一网打尽枚举操作 .net core
- Jenkins 发布.net core 程序,服务端无法下载nuget包的解决方法 error NU1102: 找不到版本为 (>= 3.1.6) 的包
- NET Core Kestrel部署HTTPS 一个服务器绑一个证书 一个服务器绑多个证书
- .net core webapi jwt 更为清爽的认证 ,续期很简单(1)