OpenCL 第8课:旋转变换(2)

上两节课都是对一个数组进行处理。这节我们来个有意思的。同样是旋转。但我们旋转的对象是张(256*256)的图片。图片旋转45度,旋转后大小还是256*256,超出部份进行剪除。

 

图片旋转处理有个特别的地方。buf_A是存储源图数据(R,G,B颜色分量),buf_B是存储旋转后数据。我们不能简单将buf_A中的数据直接计算旋转后位置。而是遍历buf_B每个数据,计算那些数据旋转后存在这个位置的数据他在buf_A的坐标是多少。为什么呢?不是因为不能直接旋转。而是因为坐标是整数型。进行旋转计算后会得出浮点数,有小数。计算精度不同。如果还用直接旋转计算方法。成出的位图将会出现斑点。大家可试下。

 

我们来看源码

rotate.cl源码

?
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
__kernel void rotation(__global int* A,
                    __global int* B,
                    int width,
                    int height,
                    float sinangle,
                    float cosangle)
{
    //获取索引号,这里是二维的,所以可以取两个
    //否则另一个永远是0
    int col = get_global_id(0);
    int row = get_global_id(1);
    //计算图形中心点
    float cx = ((float)width)/2;
    float cy = ((float)height)/2;
    int nx = (int)(cx + cosangle * ((float)col-cx) + sinangle * ((float)row-cy));
    int ny = (int)(cy + (-1*sinangle) * ((float)col-cx) + cosangle * ((float)row-cy));
    //边界检测
    if(nx>=0 && nx<width && ny>=0 && ny<height)
    {
        B[col*3+0+row*width*3] = A[nx*3+0+ny*width*3];
        B[col*3+1+row*width*3] = A[nx*3+1+ny*width*3];
        B[col*3+2+row*width*3] = A[nx*3+2+ny*width*3];
    }
}

main.cpp源码

?
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <conio.h>
#include <math.h>//数学库
#include <CL/cl.h>//包含CL的头文件
//调用freeimage
#include <freeimage.h>
using namespace std;
//8x8数组
const int dim_x = 256;
const int dim_y = 256;
//45度的弧度
const float angle = 3.1415926f/4.0f;
static int buf_A[dim_x*dim_y*3];
static int buf_B[dim_x*dim_y*3];
//加载图片
//以RGBA格式存储图片
static bool LoadImg(const char* fname)
{
    //初始化FreeImage
    FreeImage_Initialise(TRUE);
    //定义图片格式为未知
    FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
    //获取图片格式
    fif = FreeImage_GetFileType(fname,0);
    //根据获取格式读取图片数据
    FIBITMAP* bitmap = FreeImage_Load(fif,fname,0);
    if(!bitmap)
    {
        printf("load error!\n");
        return false;
    }
    int x,y;
    RGBQUAD m_rgb;
    //获取图片长宽
    int width = (int)FreeImage_GetWidth(bitmap);
    int height = (int)FreeImage_GetHeight(bitmap);
    //获取图片数据
    //按RGBA格式保存到数组中
    for(y=0;y<height;y++)
    {
        for(x=0;x<width;x++)
        {
            //获取像素值
            FreeImage_GetPixelColor(bitmap,x,y,&m_rgb);
            //将RGB值存入数组
            buf_A[y*width*3+x*3+2] = m_rgb.rgbRed;
            buf_A[y*width*3+x*3+1] = m_rgb.rgbGreen;
            buf_A[y*width*3+x*3+0] = m_rgb.rgbBlue;
        }
    }
    FreeImage_Unload(bitmap);
    return true;
}
static bool SaveImg()
{
    //初始化FreeImage
    FreeImage_Initialise(TRUE);
    FIBITMAP* bitmap =FreeImage_Allocate(dim_x,dim_y,32,8,8,8);
    int m,n;
    for(n=0;n<dim_y;n++)
    {
        BYTE *bits =FreeImage_GetScanLine(bitmap,n);
        for(m=0;m<dim_x;m++)
        {
            bits[0] = buf_B[dim_x*3*n+m*3+0];
            bits[1] = buf_B[dim_x*3*n+m*3+1];
            bits[2] = buf_B[dim_x*3*n+m*3+2];
            bits[3] = 255;
            bits+=4;
        }
    }
    //保存图片为PNG格式
    if(false ==FreeImage_Save(FIF_PNG, bitmap,"rotate.png", PNG_DEFAULT))
    {
        printf("save image error\n");
    }
    FreeImage_Unload(bitmap);
    return true;
}
//从外部文件获取cl内核代码
bool GetFileData(const char* fname,string& str)
{
    FILE* fp = fopen(fname,"r");
    if(fp==NULL)
    {
        printf("no found file\n");
        return false;
    }
    while(feof(fp)==0)
    {
        str += fgetc(fp);
    }
    return true;
}
int main()
{
    if(LoadImg("bk.png")==false)
    {
        printf("error load bk.png!\n");
        return 0;
    }
    //先读外部CL核心代码,如果失败则退出。
    //代码存buf_code里面
    string code_file;
    if(false == GetFileData("rotate.cl",code_file))
    {
        printf("Open rotate.cl error\n");
        return 0;
    }
    char* buf_code = new char[code_file.size()];
    strcpy(buf_code,code_file.c_str());
    buf_code[code_file.size()-1] = NULL;
    //声明CL所需变量。
    cl_device_id device;
    cl_platform_id platform_id = NULL;
    cl_context context;
    cl_command_queue cmdQueue;
    cl_mem bufferA,bufferB;
    cl_program program;
    cl_kernel kernel = NULL;
    //我们使用的是二维向量
    //设定向量大小(维数)
    size_t globalWorkSize[2];
    globalWorkSize[0] = dim_x;
    globalWorkSize[1] = dim_y;
    cl_int err;
    /*
        定义输入变量和输出变量,并设定初值
    */
    size_t datasize = sizeof(int) * dim_x * dim_y * 3;
    //step 1:初始化OpenCL
    err = clGetPlatformIDs(1,&platform_id,NULL);
    if(err!=CL_SUCCESS)
    {
        cout<<"clGetPlatformIDs error:"<<err<<endl;
        return 0;
    }
    //这次我们只用CPU来进行并行运算,当然你也可以该成GPU
    clGetDeviceIDs(platform_id,CL_DEVICE_TYPE_CPU,1,&device,NULL);
    //step 2:创建上下文
    context = clCreateContext(NULL,1,&device,NULL,NULL,NULL);
    //step 3:创建命令队列
    cmdQueue = clCreateCommandQueue(context,device,0,NULL);
    //step 4:创建数据缓冲区
    bufferA = clCreateBuffer(context,
                             CL_MEM_READ_ONLY,
                             datasize,NULL,NULL);
    bufferB = clCreateBuffer(context,
                             CL_MEM_WRITE_ONLY,
                             datasize,NULL,NULL);
    //step 5:将数据上传到缓冲区
    clEnqueueWriteBuffer(cmdQueue,
                         bufferA,CL_FALSE,
                         0,datasize,
                         buf_A,0,
                         NULL,NULL);
    //step 6:加载编译代码,创建内核调用函数
    program = clCreateProgramWithSource(context,1,
                                        (const char**)&buf_code,
                                        NULL,NULL);
    clBuildProgram(program,1,&device,NULL,NULL,NULL);
    kernel = clCreateKernel(program,"rotation",NULL);
    //step 7:设置参数,执行内核
    float sinangle = sinf(angle);
    float cosangle = cosf(angle);
    clSetKernelArg(kernel,0,sizeof(cl_mem),&bufferA);
    clSetKernelArg(kernel,1,sizeof(cl_mem),&bufferB);
    clSetKernelArg(kernel,2,sizeof(cl_int),&dim_x);
    clSetKernelArg(kernel,3,sizeof(cl_int),&dim_y);
    clSetKernelArg(kernel,4,sizeof(cl_float),&sinangle);
    clSetKernelArg(kernel,5,sizeof(cl_float),&cosangle);
    //注意这里第三个参数已经改成2,表示二维数据。
    clEnqueueNDRangeKernel(cmdQueue,kernel,
                           2,NULL,
                           globalWorkSize,
                           NULL,0,NULL,NULL);
    //step 8:取回计算结果
    clEnqueueReadBuffer(cmdQueue,bufferB,CL_TRUE,0,
                        datasize,buf_B,0,NULL,NULL);
    SaveImg();
    //释放所有调用和内存
    clReleaseKernel(kernel);
    clReleaseProgram(program);
    clReleaseCommandQueue(cmdQueue);
    clReleaseMemObject(bufferA);
    clReleaseMemObject(bufferB);
    clReleaseContext(context);
    delete buf_code;
    return 0;
}

 

源图

bk

 

旋转后图

rotate

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/447939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VUE: 当前页面 引用自定义公用样式 (:style=“样式名“)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在当前页面&#xff0c;自行定义了几个样式&#xff0c;在不同地方引用。 2. 实现代码。 样式定义&#xff1a; data() {return {i…

Visual Studio 使用说明文档、VScode 使用手册

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我只是记录下地址&#xff0c;方便自已以后查看&#xff1a; Visual Studio 使用文档 内容如&#xff1a;

“ 紫手环的力量 ” :我想,美好的生活应该是自已造就的...

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 我想或许我可以试试这个方法&#xff1a; 其实 我是真的打算试试&#xff0c;最近总是会忧虑&#xff0c;或许我应该自已努力给自已造就…

解决 VUE:[WDS] Errors while compiling. Reload prevented...- invalid expression: Unexpected token -- in

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 在网上找了个组件&#xff0c;直接把代码放入自已的项目中报错&#xff0c;提示信息如黑框中&#xff1a; 2. 此组件原码就是这样用的…

linux 上 日志中查异常,指定显示异常前后日志内容

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 查异常cat -n abc.log |grep Exception|more如找到行数为&#xff1a;5201314行&#xff0c;再查看该行前后的异常信息cat -n abc.log |…

my40_MySQL锁概述之意向锁

本文在锁概述的基础上&#xff0c;通常实验举例&#xff0c;详细地介绍了意向锁的原理。 锁范围 全局锁&#xff08;global lock&#xff09;表锁&#xff08;table lock&#xff09;行锁 (row lock) ROW LOCK的粒度LOCK_REC_NOG_GAP, record lock with out gap lockLOCK_GAP&…

C语言的整型溢出问题

整型溢出有点老生常谈了&#xff0c;bla, bla, bla… 但似乎没有引起多少人的重视。整型溢出会有可能导致缓冲区溢出&#xff0c;缓冲区溢出会导致各种黑客攻击&#xff0c;比如最近OpenSSL的heartbleed事件&#xff0c;就是一个buffer overread的事件。在这里写下这篇文章&…

Thymeleaf 简介、教程

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Thymeleaf是一个适用于Web和独立环境的现代服务器端Java模板引擎。 Thymeleaf的主要目标是为您的开发工作流程带来优雅的自然模板 - 可…

如期而至,GCC 4.9.0正式版发布!

摘要&#xff1a;GCC是一套由GNU开发的编程语言编译器。近日&#xff0c;GCC 4.9.0发布&#xff0c;主要新特性包括&#xff1a;提升了C11和C14特性&#xff1b;诊断信息支持彩色显示&#xff1b;移除mudflap运行时检查器等。 如期而至&#xff0c;GCC 4.9.0发布&#xff0c;该…

《 追风筝的人 》:“ 为你,千千万万遍 ” ...

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 刚来研发中心的时候&#xff0c;在我的新位置上发现了一本书&#xff0c;问后得知是前同事留下的&#xff0c;已无主 。 我就收下了。一…

广州科目三考试 不得不看的十条提醒(图)

导读&#xff1a; 考试科目三时考试常会有点小紧张。经常会有考生因为紧张犯了些小错误而被pass掉。如何来应对呢&#xff1f;首先是放松心态&#xff0c;这点其实大家都明白&#xff0c;只是做不到。有人一到考试的时候就紧张&#xff0c;完全思维混乱&#xff0c;动作僵硬。建…

HDU 6706 huntian oy

题意 求以下式子的值&#xff0c;T组数据各个字母满足1 ≤ n , a , b ≤109 &#xff0c;a,b互质 思路&#xff1a; 卡常毒瘤题&#xff0c;出题人时限卡的非常紧&#xff0c;考场上推出来又T又WA 1 #include<bits/stdc.h>2 using namespace std;3 typedef long long ll;…

linux 查看空间(内存、磁盘、文件目录、分区)的几个命令

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. free free命令用于显示内存状态。 free指令会显示内存的使用情况&#xff0c;包括实体内存&#xff0c;虚拟的交换文件内存&#x…

广州学车科目三路考操作步骤要领

广州学车&#xff0c;科目三路考操作步骤是关键&#xff0c;许多朋友明明会开车&#xff0c;却因为一些步骤上的小疏忽而不得到不补考&#xff0c;今天总结出这个广州学车科目三路考操作步骤要领&#xff0c;希望对大家有帮助&#xff1a; 广州学车&#xff0c;科目三路考操作步…

如何和何时使用 CSS 的权重设置 !important (建议:永不使用!)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 特别声明&#xff1a;此篇文章由David根据Louis Lazaris的英文文章原名《!important CSS Declarations: How and When to Use Them》进行…

广州科目三电子考需注意哪些问题?

广州驾考科目三从4月1日起开始试行电子评判与人工评判相结合的新制度&#xff0c;即电子路考&#xff0c;多数学员对新制度表示不适应&#xff0c;那么&#xff0c;科目三电子路考需要注意哪些问题? 从4月1日开始&#xff0c;科目三考试将试行计算机辅助与人工评判相结合的制度…

解决 VUE: 本地运行和服务器上运行样式不一致,run、build 运行时样式有出入

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 我的情况&#xff1a; 我遇到 2 种情况&#xff0c;一个是表格的分页样式有变化。另一个是导航菜单样式有变化。 2. 解决&#xff…

开发中的“软”与“硬”:高画质移动游戏开发之道

摘要&#xff1a;游戏的效果不仅与游戏引擎的渲染相关&#xff0c;与硬件优化也有千丝万缕的联系。一款基于芯片优化的移动游戏界面&#xff0c;甚至可以堪比视频游戏的视觉效果。高通半导体事业部资深经理刘晓光从软硬件两个层面分享了移动游戏开发之道。 在今年的Unity亚洲开…

解决 VUE: [Vue warn]: Do not use built-in or reserved HTML elements as component id: xx

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 新增一个组件&#xff0c;运行无问题&#xff0c;但F12报错&#xff1a; vue.esm.js?efeb:591 [Vue warn]: Do not use built-in o…

Linux系统重置和修改root密码

Linux系统经常会出现忘记root密码的情况&#xff0c;写下此随笔&#xff0c;以便记忆和学习。 一、重置root密码的步骤如下&#xff1a; 1.如果系统是开机状态&#xff0c;重启一下。进到下面这个界面按字母“e”键。 2.找到 linux16这一行&#xff0c;将下图红框中的内容修改为…