OpenCL 第7课:旋转变换(1)

旋转是一个常用的处理功能。图片中所有的点以某一个点为轴,顺时或逆时方向旋转N个角度。我们利用OpenCL就可以对图片中所有的点进行并行转换,大大提高效率。

上两节中,我们编写了CL文件来传递数组的地址,这一节中我们会多加入几个参数传递。

首先我们先来看下图片旋转的原理。这里我们假设图片的旋转是以图片的中心点为轴。也就是(width/2,height/2)这个点。旋转的角度是任意值。图片旋转会出现这两种情况。

TM截图20130327230153

第一幅是原图,第二幅是旋转了30度,大家可以看到旋转后图片的一部份数据已经超出了原来图片的大小范围。怎么处理超出部份的数据呢。因为我们的图片数据是用数组来存储的,一般我们有两个方法,1、存储图片的数组做大些。2、超出图片部份的数据不显示。这里我们选择后者,方便。

 

下面我们来看下rotate.cl程序和主程序。

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
__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[nx + ny*width] = A[col + row*width];
    }
}

主程序

?
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
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <conio.h>
#include <math.h>//数学库
#include <CL/cl.h>//包含CL的头文件
using namespace std;
//8x8数组
const int dim_x = 8;
const int dim_y = 8;
//45度的弧度
const float angle = 3.1415926f/4.0f;
//从外部文件获取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()
{
    //先读外部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;
    int m,n;
    int buf_A[] = {0,0,0,1,1,0,0,0,
                   0,0,1,0,0,1,0,0,
                   0,1,0,0,0,0,1,0,
                   1,1,1,0,0,1,1,1,
                   0,0,1,0,0,1,0,0,
                   0,0,1,0,0,1,0,0,
                   0,0,1,0,0,1,0,0,
                   0,0,1,1,1,1,0,0,};
//输出数组初始为-1,即该位置不显示数字
    int buf_B[] = {-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};
    //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_GPU,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);
    //输出计算结果
    for(n=0;n<dim_x;n++)
    {
        for(m=0;m<dim_y;m++)
        {
            if(buf_A[m+dim_x*n]==0)
                cout<<"  ";
            else
                cout<< buf_A[m+dim_x*n] <<" ";
        }
        cout<<endl;
    }
    cout<<endl<<"====Rotate 45===="<<endl<<endl;
    for(n=0;n<dim_x;n++)
    {
        for(m=0;m<dim_y;m++)
        {
            if(buf_B[m+dim_x*n]<=0)
                cout<<"  ";
            else
                cout<< buf_B[m+dim_x*n] <<" ";
        }
        cout<<endl;
    }
    //释放所有调用和内存
    clReleaseKernel(kernel);
    clReleaseProgram(program);
    clReleaseCommandQueue(cmdQueue);
    clReleaseMemObject(bufferA);
    clReleaseMemObject(bufferB);
    clReleaseContext(context);
    delete buf_code;
    return 0;
}

程序运行结果:

TM截图20130327230153

为什么旋转后图形不规整呢?这是因为图片的大小和运算的精度不够。主要是图片的大小不够,一个8X8的图你还能指望他能好成啥样啊!

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

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

相关文章

WinForms多线程编程之摇奖程序

利用多线程模拟一个电脑摇奖程序&#xff0c;如图所示。在点击【滚动号码】&#xff0c;启动线程&#xff0c;对后台的电话号码进行循环显示&#xff1b;点击【开奖】按钮&#xff0c;关闭线程&#xff0c;此时显示在文本框中的电话号码即为中奖号码 using System;using System…

idea 版本控制忽略文件、文件夹设置

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 setting 中&#xff1a; 或者底部的 设置 忽略某个文件 后面选择框可以去选择 忽略某个文件夹 后面选择框可以去选择 忽略某种文件 后面…

Windows Azure HandBook (1) IaaS相关技术

《Windows Azure Platform 系列文章目录》 1.Microsoft Azure底层是否由System Center和Hyper-V构成? Microsoft Azure虽然支持Hyper-V的VHD直接上传至Azure云端进行管理&#xff0c;但是Azure底层技术是微软自己研发的、独有的技术&#xff0c;且不对外提供。如果客户想构建属…

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

上两节课都是对一个数组进行处理。这节我们来个有意思的。同样是旋转。但我们旋转的对象是张&#xff08;&#xff12;&#xff15;&#xff16;*&#xff12;&#xff15;&#xff16;&#xff09;的图片。图片旋转&#xff14;&#xff15;度&#xff0c;旋转后大小还是&…

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

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

免费的api接口

欢迎大家加群讨论&#xff1a;地址&#xff1a;https://www.apiopen.top 为了方便各类开发者&#xff0c;现提供免费开放Api接口&#xff0c;所有接口均无使用限制&#xff0c;返回格式全是JSON&#xff0c;所以基本能满足大家的开发需求&#xff0c;但请各位不要将这些Api接入…

养成这8个好习惯 开车会很安全的

第一&#xff0c;过路口时减速左右看——要养成过口子时&#xff0c;不管有没有红绿灯&#xff0c;也不管自己的行道是绿灯&#xff0c;都要左顾右盼&#xff08;同时要减速&#xff09;的习惯&#xff0c;观察在横道上的车辆情况&#xff0c;确认没有车横冲&#xff0c;才加速…

css background-attachment:fixed 固定背景、不随内容一起滚动

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 兼容性&#xff1a;全兼容&#xff0c;只不过IE滚动时会有一点不流畅。 background-attachment 有 3 个选项&#xff1a;scroll / fix…

Javacript和AngularJS中的Promises

promise是Javascript异步编程很好的解决方案。对于一个异步方法&#xff0c;执行一个回调函数。比如页面调用google地图的api时就使用到了promise。 function success(position){var cords position.coords;console.log(coords.latitude coords.longitude); }function error(…

男人沉默的真实原因

英国社会学家马克经过调查发现&#xff1a;男人每天的说话量&#xff0c;是女人的一半。但男人们也大多用于朋友圈中、工作中&#xff0c;而与爱人的聊天交流&#xff0c;每天可能不足15分钟&#xff0c;用词量不超过10%。 其实&#xff0c;男人有很多缄默的方法&#xff0c;每…

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

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

JAVA File的创建及相对路径绝对路径

JAVA File的创建及相对路径绝对路径 转载自 http://blog.sina.com.cn/s/blog_9386f17b0100w2vv.htmlFile f new File("D:/test/mytest.txt");//当执行这句话后在内存的栈空间存在一个f的应用&#xff0c;在堆空间里存在一个mytest.txt对象。注意 这个对象只含有文件…

肾有多好人就有多年轻 男女通用的补肾秘方

每天都坚持喝一碗&#xff0c;现在已经连续喝了三个多星期了&#xff0c;以前有好些白发的地方居然没有复发&#xff0c;而且现在一根也没有啊&#xff0c;我真的很开心。不仅白头发不见了&#xff0c;而且皮肤变白皙和光滑了好多&#xff0c;气色也比原来好了!好东西要大家分享…

Object.keys() Object.values()

Object.keys() //返回对象中各个键值对的键(key) Object.values() //返回对象中各个键值对的值(value) var obj { foo: "bar", baz: 42 };Object.keys(obj) // ["foo", "baz"]Object.values(obj) // ["ba…

vue 解决: *!!vue-style-loader!css-loader?{“sourceMap“:true}!../../../../vue-loader

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 问题描述 *!!vue-style-loader!css-loader?{“sourceMap”:true}!../../../../vue-loader/lib/style-compiler/index?{“vue”:true,…

计算机专业 程序员技术练级攻略(转载)

程序员技术练级攻略转载自: https://coolshell.cn/articles/4990.html 前言 你是否觉得自己从学校毕业的时候只做过小玩具一样的程序&#xff1f;走入职场后哪怕没有什么经验也可以把以下这些课外练习走一遍&#xff08;朋友的抱怨&#xff1a;学校课程总是从理论出发&#xff…

35 岁之前不应该错过的 30 本书

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 PS&#xff1a;在这个书目中&#xff0c;我不偏好的书会直接放到最后&#xff0c;所以不是按原文顺序来。 1、《目送》 作者&#xff1a…

生活中意想不到的妙招

1、抹布变白 抹布是咱们家中最常见的东西&#xff0c;干家务绝对离不开它&#xff0c;擦桌椅板凳&#xff0c;擦灶台&#xff0c;油烟机&#xff0c;浴室&#xff0c;电器等等&#xff0c;家里总需要准备很多抹布&#xff0c;最难清理的恐怕就是厨房的抹布了吧?因为总是和油污…

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

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

通过界面生成时不存在的数据刷新界面引起的卡顿问题

今天遇到了一个问题&#xff0c;就是有一个界面&#xff0c;在生成时之前请求数据&#xff0c;在界面中通过schedule 与unschedule不停查看本地是否收到此数据&#xff08;通过发起request的Id&#xff09;&#xff0c;当收到之后刷新。 然后就引起了一个问题。界面弹出是有动画…