【CV学习笔记】图像预处理warpaffine-cuda加速
1、前言
在上个学习笔记中学习warpaffine,并且在opencv下面实现了图像的预处理,而warpaffine可以很好的利用cuda加速来实现,于是基于手写AI的项目,又学习了warpaffien在cuda上的加速。
原项目地址为:https://github.com/shouxieai/tensorRT_Pro
个人学习项目地址为:https://github.com/Rex-LK/tensorrt_learning
欢迎正在学习或者想学的CV的同学进群一起讨论与学习,v:Rex1586662742,q群:468712665
2、学习内容
2.1、双线性插值
在缩放后的原图恢复到原图或者模型得到的结果需要恢复的原尺寸需要用到双线性差值,双向性差值的基本原理是靠近谁,谁的权重就大,可由下图表示
图中点p 的值由起周围的p1 ~ p4 四个值的确定,p1 的权重为正方形D的面积占总面试的比例,p2的权重为正方形C占总面积的比例。代码如下:
# p1 ~ p4 的值
p1 = 1
p2 = 2
p3 = 8
p4 = 12# p1~p4 位四个相邻的像素,围起来的面积为1p = 0.6,0.8p1_w = (1 - p[0]) * (1 - p[1])
p2_w = p[0] * (1 - p[1])
p3_w = (1 - p[0]) * p[1]
p4_w = p[0] * p[1]res = p1 * p1_w + p2 * p2_w + p3 * p3_w + p4 * p4_w
print(res)
下面将利用双线性差值来实现warpaffine
import cv2
import numpy as np
import matplotlib.pyplot as plt def myWarpaffine(img,M,d_size,constant=(0, 0, 0)):# 其中 M 为 原图变为目标图的变换矩阵,将缩放后的图恢复到原图需要取逆变换M_inv = cv2.invertAffineTransform(M)constant = np.array(constant)o_h, o_w = img.shape[:2]d_h, d_w = d_sizedst_img = np.full((d_h, d_w, 3), constant, dtype=np.uint8)o_range = lambda p: p[0] >= 0 and p[0] < o_w and p[1] >= 0 and p[1] < o_hfor y in range(d_h):for x in range(d_w):# 缩放后图上的一点homogeneous = np.array([[x, y, 1]]).T# 恢复到原图的尺寸ox, oy = M_inv @ homogeneous# p1 p2# p# p3 p4#np.floor(ox) 类型为np.float64low_ox = int(np.floor(ox))low_oy = int(np.floor(oy))high_ox = low_ox + 1high_oy = low_oy + 1p = ox - low_ox, oy - low_oyp1_w = (1 - p[0]) * (1 - p[1])p2_w = p[0] * (1 - p[1])p3_w = (1 - p[0]) * p[1]p4_w = p[0] * p[1]p1 = low_ox, low_oyp2 = high_ox, low_oyp3 = low_ox, high_oyp4 = high_ox, high_oy# 避免超出图片范围p1_value = img[p1[1], p1[0]] if o_range(p1) else constantp2_value = img[p2[1], p2[0]] if o_range(p2) else constantp3_value = img[p3[1], p3[0]] if o_range(p3) else constantp4_value = img[p4[1], p4[0]] if o_range(p4) else constantdst_img[y, x] = p1_w * p1_value + p2_w * p2_value + p3_w * p3_value + p4_w * p4_value return dst_imgif __name__ == "__main__"img_o = cv2.imread("/home/rex/Desktop/rex_extra/notebook/warpaffine/keji2.jpeg")# 图片旋转中心、旋转角度、缩放倍数M = cv2.getRotationMatrix2D((0, 0), -30, 0.6)or_test = cv2.warpAffine(img_o, M, (640, 640))my_test = myWarpaffine(img_o,M,(640, 640))plt.figure(figsize=(10, 10))plt.subplot(1, 2, 1)plt.title("opencv")#BGR -> RGBplt.imshow(or_test[...,::-1])plt.subplot(1, 2, 2)plt.title("pyWarpaffine")# BGR -> RGBplt.imshow(my_test[...,::-1])
可以得到如下结果,左图为opencv实现的效果,右图为自定义实现的结果,发现结果一致,说明自己实现的双线性差值的warpaffine是正确的。
有了上述的铺垫之后,接下来正式进入warpaffine在cuda上的加速
2.3、warpaffine-cuda加速
将warpaffine在cuda上进行加速,其核函数如下
__global__ void warp_affine_bilinear_kernel(uint8_t* src, int src_line_size, int src_width, int src_height, uint8_t* dst, int dst_line_size, int dst_width, int dst_height, uint8_t fill_value, AffineMatrix matrix
){// 线程ID的全局索引int dx = blockDim.x * blockIdx.x + threadIdx.x; int dy = blockDim.y * blockIdx.y + threadIdx.y;// 线程ID 超过图像大小时 returnif (dx >= dst_width || dy >= dst_height) return;// 目标图像为640*640*3 用fill_value填充float c0 = fill_value, c1 = fill_value, c2 = fill_value;float src_x = 0; float src_y = 0;//将目标图上一点映射回原图大小affine_project(matrix.d2i, dx, dy, &src_x, &src_y);if(src_x < -1 || src_x >= src_width || src_y < -1 || src_y >= src_height){// out of range// src_x < -1,high_x < 0,超出范围// src_x >= -1,high_x >= 0,存在取值}else{// p1 p2// p// p3 p4int y_low = floorf(src_y);int x_low = floorf(src_x);int y_high = y_low + 1;int x_high = x_low + 1;uint8_t const_values[] = {fill_value, fill_value, fill_value};//双线性差值,和python版一致float ly = src_y - y_low;float lx = src_x - x_low;float hy = 1 - ly;float hx = 1 - lx;float w1 = hy * hx, w2 = hy * lx, w3 = ly * hx, w4 = ly * lx;uint8_t* v1 = const_values;uint8_t* v2 = const_values;uint8_t* v3 = const_values;uint8_t* v4 = const_values;if(y_low >= 0){if (x_low >= 0)v1 = src + y_low * src_line_size + x_low * 3;if (x_high < src_width)v2 = src + y_low * src_line_size + x_high * 3;}if(y_high < src_height){if (x_low >= 0)v3 = src + y_high * src_line_size + x_low * 3;if (x_high < src_width)v4 = src + y_high * src_line_size + x_high * 3;}// 该点的像素值c0 = floorf(w1 * v1[0] + w2 * v2[0] + w3 * v3[0] + w4 * v4[0] + 0.5f);c1 = floorf(w1 * v1[1] + w2 * v2[1] + w3 * v3[1] + w4 * v4[1] + 0.5f);c2 = floorf(w1 * v1[2] + w2 * v2[2] + w3 * v3[2] + w4 * v4[2] + 0.5f);}uint8_t* pdst = dst + dy * dst_line_size + dx * 3;pdst[0] = c0; pdst[1] = c1; pdst[2] = c2;//BGR -> RGB// pdst[2] = c0; pdst[1] = c1; pdst[2] = c0;// (p - mean) / std // pdst[0] = (c0 - mean) / std; pdst[1] = (c1 - mean) / std; pdst[2] = (c2 - mean) / std;
}
2.4 warpaffine-cuda 加速测试
通过配置CMakeLists.txt中的 tensorrt以及其他路径即可,测试结果如下
通过一个核函数可以实现 图像的预处理 、标准化、BGR -> RGB,由此可以利用cuda实现warpaffine是十分高效的,其测试代码也可以在个人gitee中找到
3、总结
本次学习内容学习了双线性差值,并利用python实现了cpu版本,利用cuda实现了gpu版本,对于图像预处理而言,极大的加速了图像预处理的速度
【CV学习笔记】图像预处理warpaffine-cuda加速相关推荐
- CV学习笔记-图像滤波器
图像滤波器 1. 图像滤波 1. 图像滤波&滤波器 图像滤波: 即在尽可能保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可不可缺少的操作,其处理效果的好坏将直接影响到后续图 ...
- CV学习笔记 — 数据集预处理常用脚本总结
笔者在学习计算机视觉时,需要经常借助脚本对数据集进行预处理,现将常用的脚本总结如下: 1. 批量修改文件后缀名 # 批量修改 import os import sys # 需要修改后缀的文件目录 os ...
- PyTorch框架学习六——图像预处理transforms(二)
PyTorch框架学习六--图像预处理transforms(二) (续)二.transforms的具体方法 4.图像变换 (1)尺寸变换:transforms.Resize() (2)标准化:tran ...
- PyTorch框架学习五——图像预处理transforms(一)
PyTorch框架学习五--图像预处理transforms(一) 一.transforms运行机制 二.transforms的具体方法 1.裁剪 (1)随机裁剪:transforms.RandomCr ...
- y空间兑换代码_【CV学习笔记】色彩空间
关注"深度学习冲鸭",一起学习一起冲鸭! 设为星标,第一时间获取更多干货 作者:云时之间来源:知乎链接:https://zhuanlan.zhihu.com/p/103387082 ...
- Task02:学习笔记文本预处理;语言模型;循环神经网络基础
Task02:学习笔记文本预处理:语言模型:循环神经网络基础 文本预处理 文本是一类序列数据,一篇文章可以看作是字符或单词的序列,本节将介绍文本数据的常见预处理步骤,预处理通常包括四个步骤: 读入文本 ...
- CV学习笔记-BP神经网络训练实例(含详细计算过程与公式推导)
BP神经网络训练实例 1. BP神经网络 关于BP神经网络在我的上一篇博客<CV学习笔记-推理和训练>中已有介绍,在此不做赘述.本篇中涉及的一些关于BP神经网络的概念与基础知识均在< ...
- cv学习笔记(3)神经网络数学原理
cv学习笔记(3)神经网络数学原理 根据一个神经网络例子来介绍 输入是年龄.收入.性别,输出是买车和不买车的概率.该神经网络包含一个输入层.一个隐含层.一个输出层,每个节点和下一层的所有节点都有连接, ...
- 【CV学习笔记】图像预处理warpaffine
1.前言 在学习图像预处理的时候发现,之前用的图像预处理方法一般为 resize和letter box,这两种方法比较低效,后来在手写AI中接触到了warpaffine,只需要一步就能够对图像进行预处 ...
最新文章
- 10分钟搞定 Java 并发队列
- 在linux将一些程序放到后台运行的方法(nohup/screen/daemonize)
- p,v原语解决和尚挑水问题
- 【跃迁之路】【545天】程序员高效学习方法论探索系列(实验阶段302-2018.08.04)...
- Visual Studio Code 打开程序文件中文乱码解决方法
- 高性能I/O设计模式Reactor和Proactor
- 【CV】基于阈值处理的图像分割算法!
- 深入掌握JMS(七):DeliveryMode例子
- Hadoop集群安装配置教程_Hadoop2.6.0_UbuntuCentOS(林子雨教授,超级详细)
- 【程序人生】Web前端工程师岗位分析报告
- Eslint报错extra semicolon的解决方法
- 电源管理(2) - loongson cpufreq
- 研究生科研素养提升的测试题
- 雷锋微视点:腾讯电商、搜搜、微信将出门独立
- python locust在windows下的安装
- 计算机系微电子专业就业前景,2019微电子技术专业就业前景和就业方向分析
- Android BLE 蓝牙开发指南(三)外围设备端开发详解
- python 涨停统计_python+tushare获取股票和基金每日涨跌停价格
- matlab用抛物线族表示马鞍面,matlab实验报告
- 使用andorid源生生成pdf的坑
热门文章
- 关于英语学习的一点看法
- 利用Saxon和xslt进行xml的格式转换
- 配电网光伏/储能双层优化配置模型(选址定容)
- AMI legacy BIOS里添加2个VBIOS的问题
- linux proftpd 用户,Proftpd配置之本地用户
- Failed to save. Insufficient permissions. When trying to save changes in VS Code
- MySQL半同步与sync_relay_log关系2
- Norton10.0 x64 病毒定义更新脚本(MS-DOS)
- 浮水法——贴海报题解
- 小程序实战--仿bilibil(哔哩哔哩)小程序