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.pswp.cn/news/447939.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/447939.shtml
英文地址,請注明出處:http://en.pswp.cn/news/447939.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

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;當收到之后刷新。 然后就引起了一個問題。界面彈出是有動畫…

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

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 在網上找了個組件&#xff0c;直接把代碼放入自已的項目中報錯&#xff0c;提示信息如黑框中&#xff1a; 2. 此組件原碼就是這樣用的…

長壽的十個秘訣 至少選擇一個堅持實施

人人都想提高自己健康長壽的機率。下面的十個秘訣中&#xff0c;哪怕只選擇一個&#xff0c;然后堅持實施&#xff0c;若干年后你會發現已經受益無窮。 1、喝茶 喝茶&#xff0c;特別是喝綠茶&#xff0c;其中的抗氧化劑可以抵擋有害物質對你身體的傷害。喝茶被證明可以減壓…

vue中的slot插槽

1.無名插槽<body><div id"app">123</div><script src"https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><script type"text/javascript">//注冊組件Vue.component("my-component",{templ…

linux 上 日志中查異常,指定顯示異常前后日志內容

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 查異常cat -n abc.log |grep Exception|more如找到行數為&#xff1a;5201314行&#xff0c;再查看該行前后的異常信息cat -n abc.log |…