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.pswp.cn/news/447943.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447943.shtml
英文地址,請注明出處:http://en.pswp.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;當收到之后刷新。 然后就引起了一個問題。界面彈出是有動畫…