对灰度图像矩阵转置:图像宽1080 高720
kernel:
__kernel void transposeMatrix(__global uchar* srcimgdata,__global uchar* dstimgdata,int width,int height)
{
int id=get_global_id(0);
for(int i=id;i<width*height;i+=get_global_size(0))
{
int dstcol=i/1080;
int dstrow=i%1080;
dstimgdata[dstrow*height+dstcol]=srcimgdata[i];
}
}
host端:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <CL/cl.h>
#include "gFreeImage.h"
void check(cl_int status) {
if (status != CL_SUCCESS) {
printf("OpenCL error (%d)\n", status);
exit(-1);
}
}
char* readFile(const char *filename) {
FILE *fp;
char *fileData;
long fileSize;
/* Open the file */
fp = fopen(filename, "r");
if (!fp) {
printf("Could not open file: %s\n", filename);
exit(-1);
}
/* Determine the file size */
if (fseek(fp, 0, SEEK_END)) {
printf("Error reading the file\n");
exit(-1);
}
fileSize = ftell(fp);
if (fileSize < 0) {
printf("Error reading the file\n");
exit(-1);
}
if (fseek(fp, 0, SEEK_SET)) {
printf("Error reading the file\n");
exit(-1);
}
/* Read the contents */
fileData = (char*)malloc(fileSize + 1);
if (!fileData) {
exit(-1);
}
if (fread(fileData, fileSize, 1, fp) != 1) {
printf("Error reading the file\n");
exit(-1);
}
/* Terminate the string */
fileData[fileSize] = '\0';
/* Close the file */
if (fclose(fp)) {
printf("Error closing the file\n");
exit(-1);
}
return fileData;
}
int main()
{
cl_int status;
cl_platform_id platform;
status = clGetPlatformIDs(1, &platform, NULL);
check(status);
cl_device_id device;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
check(status);
cl_context context;
context = clCreateContext(NULL, 1, &device, NULL, NULL, &status);
check(status);
cl_command_queue cmdQueue=clCreateCommandQueue(context, device, 0, &status);
check(status);
int imageCols, imageRows;
gFreeImage img;
int readflag=img.LoadImageGrey("/home/jumper/OpenCL_projects/MatrixTransposition/cat.bmp");
unsigned char *hInputImage = img.getImageDataGrey(imageCols,imageRows);
const int imageElements = imageRows*imageCols;
const size_t imageSize = imageElements*sizeof(unsigned char);
cl_mem bufInputImage = clCreateBuffer(context, CL_MEM_READ_ONLY, imageSize, NULL,&status);
cl_mem bufOutputImage = clCreateBuffer(context, CL_MEM_WRITE_ONLY, imageSize, NULL,&status);
check(status);
int zero = 0;
status = clEnqueueFillBuffer(cmdQueue, bufOutputImage, &zero,sizeof(int), 0, imageSize, 0, NULL, NULL);
check(status);
status = clEnqueueWriteBuffer(cmdQueue, bufInputImage, CL_TRUE, 0, imageSize,(void*)hInputImage, 0, NULL, NULL);
check(status);
char *programSource = readFile("/home/jumper/OpenCL_projects/MatrixTransposition/mine.cl");
size_t programSourceLen = strlen(programSource);
cl_program program = clCreateProgramWithSource(context, 1,(const char**)&programSource, &programSourceLen, &status);
check(status);
status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
//std::cout<<status<<std::endl;
if (status != CL_SUCCESS) {
printf("cannot build program successfully!\n");
size_t logSize;
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,0, NULL, &logSize);
char *log = (char*)malloc(logSize);
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,logSize, log, NULL);
printf("%s\n", log);
free(log);
exit(-1);
}
cl_kernel kernel;
kernel = clCreateKernel(program, "transposeMatrix", &status);
check(status);
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &bufInputImage);
status |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &bufOutputImage);
status |= clSetKernelArg(kernel, 2, sizeof(int), &imageCols);
status |= clSetKernelArg(kernel, 3, sizeof(int), &imageRows);
check(status);
size_t globalWorkSize[1]={1024};
size_t localWorkSize[1]={128};
status = clEnqueueNDRangeKernel(cmdQueue, kernel, 1, NULL,globalWorkSize, localWorkSize, 0, NULL, NULL);
std::cout<<status<<std::endl;
check(status);
unsigned char*Outputimg = (unsigned char*)malloc(imageSize);
if (!Outputimg) { exit(-1); }
status = clEnqueueReadBuffer(cmdQueue, bufOutputImage, CL_TRUE, 0,imageSize, Outputimg, 0, NULL, NULL);
check(status);
for(int i = 0; i < imageSize; i++)
{
hInputImage[i] =Outputimg[i];
}
img.SaveImage("/home/jumper/OpenCL_projects/MatrixTransposition/cat_transposition.bmp");
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(cmdQueue);
clReleaseMemObject(bufInputImage);
clReleaseMemObject(bufOutputImage);
clReleaseContext(context);
free(Outputimg);
free(programSource);
return 0;
}
结果:
还存在问题,我再想想。
找到FreeImage库中新建一幅指定大小的图 :
#include "gFreeImage.h"
bool SaveImage(char *fileName,unsigned char *buffer, int width, int height)
{
FREE_IMAGE_FORMAT format = FreeImage_GetFIFFromFilename(fileName);
FIBITMAP *image = FreeImage_ConvertFromRawBits((BYTE*)buffer, height,width, height, 8,0, 0, 0);
return (FreeImage_Save(format, image, fileName) == TRUE) ? true : false;
}
用它保存,但保存出来是全黑的 如 https://sourceforge.net/p/freeimage/discussion/36110/thread/17f61136/ 遇到的一样。可以保存彩图 但灰度图保存出来是黑的。why?
这个问题至今没解决 谷歌到 http://m.blog.naver.com/sogangori/220701976219 一个韩国人写的FreeImage的读写图像 第4点和第5点分别是将数据保存为灰度图保存至本地、将数据保存为彩图 但我试了 只有彩图是成功的 灰度图出来始终是全黑:
结果:
如果有人知道,请告知。
我写了个简单的矩阵转置做实验:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <CL/cl.h>
#include "gFreeImage.h"
void check(cl_int status);
char* readFile(const char *filename);
int main()
{
cl_int status;
cl_platform_id platform;
status = clGetPlatformIDs(1, &platform, NULL);
check(status);
cl_device_id device;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
check(status);
cl_context context;
context = clCreateContext(NULL, 1, &device, NULL, NULL, &status);
check(status);
cl_command_queue cmdQueue=clCreateCommandQueue(context, device, 0, &status);
check(status);
int imageCols=3, imageRows=4;
size_t imageSize=imageCols*imageRows*sizeof(int);
int *hInputImage=(int*)malloc(imageSize);
std::cout<<"input matrix..."<<std::endl;
for(int i=0;i<imageRows;i++)
{
for(int j=0;j<imageCols;j++)
{
int init=i+j*2;
hInputImage[i*imageCols+j]=init;
std::cout<<init<<" ";
}
std::cout<<std::endl;
}
std::cout<<std::endl;
cl_mem bufInputImage = clCreateBuffer(context, CL_MEM_READ_ONLY, imageSize, NULL,&status);
cl_mem bufOutputImage = clCreateBuffer(context, CL_MEM_WRITE_ONLY, imageSize, NULL,&status);
check(status);
int zero = 0;
status = clEnqueueFillBuffer(cmdQueue, bufOutputImage, &zero,sizeof(int), 0, imageSize, 0, NULL, NULL);
check(status);
status = clEnqueueWriteBuffer(cmdQueue, bufInputImage, CL_TRUE, 0, imageSize,(void*)hInputImage, 0, NULL, NULL);
check(status);
char *programSource = readFile("/home/jumper/OpenCL_projects/MatrixTransposition/notImg.cl");
size_t programSourceLen = strlen(programSource);
cl_program program = clCreateProgramWithSource(context, 1,(const char**)&programSource, &programSourceLen, &status);
check(status);
status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
//std::cout<<status<<std::endl;
if (status != CL_SUCCESS) {
printf("cannot build program successfully!\n");
size_t logSize;
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,0, NULL, &logSize);
char *log = (char*)malloc(logSize);
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,logSize, log, NULL);
printf("%s\n", log);
free(log);
exit(-1);
}
cl_kernel kernel;
kernel = clCreateKernel(program, "transpose", &status);
check(status);
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &bufInputImage);
status |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &bufOutputImage);
status |= clSetKernelArg(kernel, 2, sizeof(int), &imageCols);
status |= clSetKernelArg(kernel, 3, sizeof(int), &imageRows);
check(status);
size_t globalWorkSize[1]={3};
size_t localWorkSize[1]={1};
status = clEnqueueNDRangeKernel(cmdQueue, kernel, 1, NULL,globalWorkSize, localWorkSize, 0, NULL, NULL);
//std::cout<<status<<std::endl;
check(status);
int*Outputimg = (int*)malloc(imageSize);
if (!Outputimg) { exit(-1); }
status = clEnqueueReadBuffer(cmdQueue, bufOutputImage, CL_TRUE, 0,imageSize, Outputimg, 0, NULL, NULL);
check(status);
std::cout<<"transpose matrix..."<<std::endl;
for(int i=0;i<imageCols;i++)
{
for(int j=0;j<imageRows;j++)
{
int pos=i*imageRows+j;
std::cout<<Outputimg[pos]<<" ";
}
std::cout<<std::endl;
}
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(cmdQueue);
clReleaseMemObject(bufInputImage);
clReleaseMemObject(bufOutputImage);
clReleaseContext(context);
free(Outputimg);
free(programSource);
free(hInputImage);
return 0;
}
cl文件:
__kernel void transpose(__global int* srcimgdata,__global int* dstimgdata,int width,int height)
{
int id=get_global_id(0);
for(int i=id;i<width*height;i+=get_global_size(0))
{
int dstcol=i/width;
int dstrow=i%width;
dstimgdata[dstrow*height+dstcol]=srcimgdata[i];
}
}
结果转置出来是正确的:
猫的图片转置的我改成了:
main部分,cl部分没有改。
bool SaveGreyimg(char* file,unsigned char* data,int width,int height){
FIBITMAP* bitmap=FreeImage_Allocate(width,height,1);
BYTE *src=new BYTE[width*height*1];
for(int i=0;i<width*height;i++)
src[i]=data[i];
FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,width,height,1,8,0,0,0,false);
FreeImage_Save(FIF_JPEG,Image,file,JPEG_BASELINE);
FreeImage_Unload(Image);
}
int main()
{
cl_int status;
cl_platform_id platform;
status = clGetPlatformIDs(1, &platform, NULL);
//check(status);
cl_device_id device;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
//check(status);
cl_context context;
context = clCreateContext(NULL, 1, &device, NULL, NULL, &status);
//check(status);
cl_command_queue cmdQueue=clCreateCommandQueue(context, device, 0, &status);
//check(status);
int imageCols, imageRows;
gFreeImage img;
int readflag=img.LoadImageGrey("/home/jumper/OpenCL_projects/MatrixTransposition/cat.bmp");
unsigned char *hInputImage = img.getImageDataGrey(imageCols,imageRows);
const int imageElements = imageRows*imageCols;
const size_t imageSize = imageElements*sizeof(unsigned char);
cl_mem bufInputImage = clCreateBuffer(context, CL_MEM_READ_ONLY, imageSize, NULL,&status);
cl_mem bufOutputImage = clCreateBuffer(context, CL_MEM_WRITE_ONLY, imageSize, NULL,&status);
//check(status);
int zero = 0;
status = clEnqueueFillBuffer(cmdQueue, bufOutputImage, &zero,sizeof(int), 0, imageSize, 0, NULL, NULL);
//check(status);
status = clEnqueueWriteBuffer(cmdQueue, bufInputImage, CL_TRUE, 0, imageSize,(void*)hInputImage, 0, NULL, NULL);
//check(status);
char *programSource = readFile("/home/jumper/OpenCL_projects/MatrixTransposition/mine.cl");
size_t programSourceLen = strlen(programSource);
cl_program program = clCreateProgramWithSource(context, 1,(const char**)&programSource, &programSourceLen, &status);
//check(status);
status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
//std::cout<<status<<std::endl;
if (status != CL_SUCCESS) {
printf("cannot build program successfully!\n");
size_t logSize;
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,0, NULL, &logSize);
char *log = (char*)malloc(logSize);
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,logSize, log, NULL);
printf("%s\n", log);
free(log);
exit(-1);
}
cl_kernel kernel;
kernel = clCreateKernel(program, "transposeMatrix", &status);
//check(status);
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &bufInputImage);
status |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &bufOutputImage);
status |= clSetKernelArg(kernel, 2, sizeof(int), &imageCols);
status |= clSetKernelArg(kernel, 3, sizeof(int), &imageRows);
//check(status);
size_t globalWorkSize[1]={1024};
size_t localWorkSize[1]={128};
status = clEnqueueNDRangeKernel(cmdQueue, kernel, 1, NULL,globalWorkSize, localWorkSize, 0, NULL, NULL);
//std::cout<<status<<std::endl;
//check(status);
unsigned char*Outputimg = (unsigned char*)malloc(imageSize);
if (!Outputimg) { exit(-1); }
status = clEnqueueReadBuffer(cmdQueue, bufOutputImage, CL_TRUE, 0,imageSize, Outputimg, 0, NULL, NULL);
//check(status);
SaveGreyimg("/home/jumper/OpenCL_projects/MatrixTransposition/transpose.jpg",Outputimg,imageRows,imageCols);
// use FreeImage to save greyscaled image but failed below!
// FIBITMAP* bitmap=FreeImage_Allocate(128,128,1);
// BYTE *src=new BYTE[128*128*1];
// for(int i=0;i<128*128;i++)
// src[i]=i;
// FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,128,128,128,8,0,0,0,false);
// FreeImage_Save(FIF_PNG,Image,"wdtest.png",0);
// FreeImage_Unload(Image);
// use FreeImage to save color image succeed.
// FIBITMAP* bitmap=FreeImage_Allocate(16,16,3);
// BYTE *src=new BYTE[1024*720*3];
// for(int i=0;i<1024*720;i++){
// src[i*3]=i;
// src[i*3+1]=i;
// src[i*3+2]=200;
// }
// FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,1024,720,1024*3,8*3,0,0,0,false);
// FreeImage_Save(FIF_BMP,Image,"saveimg2.bmp");
// FreeImage_Unload(Image);
std::cout<<FreeImage_GetVersion()<<std::endl;
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(cmdQueue);
clReleaseMemObject(bufInputImage);
clReleaseMemObject(bufOutputImage);
clReleaseContext(context);
free(Outputimg);
free(programSource);
return 0;
}
但仍旧是一张全黑的图片啊!
但我将返回于host的这个buffer输出即将这个Outputimg去统计非0值 有很多非0啊,怎么保存时竟然是转置后的黑图呢?所以只有一种可能,保存的函数时出错了?刚刚已经自我解决,但我不是用的FreeImage 而是改用了opencv实现返回host端的buffer保存为灰度图。 但用FreeImage实现的我已经放弃了。如果有大神知道,也可以告诉我。
我最后的:main.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <CL/cl.h>
#include "gFreeImage.h"
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
char* readFile(const char *filename);
//bool SaveImage(char *fileName,unsigned char *buffer, int width, int height)
//{
// FREE_IMAGE_FORMAT format = FreeImage_GetFIFFromFilename(fileName);
// FIBITMAP *image = FreeImage_ConvertFromRawBits((BYTE*)buffer, width,height,1, 8,0, 0, 0,false);
// return (FreeImage_Save(format, image, fileName) == TRUE) ? true : false;
//}
bool SaveGreyimg(char* file,unsigned char* data,int width,int height){
FIBITMAP* bitmap=FreeImage_Allocate(width,height,1);
BYTE *src=new BYTE[width*height*1];
for(int i=0;i<width*height;i++)
src[i]=data[i];
FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,width,height,1,8,0,0,0,false);
FreeImage_Save(FIF_JPEG,Image,file,JPEG_BASELINE);
FreeImage_Unload(Image);
}
int main()
{
cl_int status;
cl_platform_id platform;
status = clGetPlatformIDs(1, &platform, NULL);
//check(status);
cl_device_id device;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
//check(status);
cl_context context;
context = clCreateContext(NULL, 1, &device, NULL, NULL, &status);
//check(status);
cl_command_queue cmdQueue=clCreateCommandQueue(context, device, 0, &status);
//check(status);
int imageCols, imageRows;
gFreeImage img;
int readflag=img.LoadImageGrey("/home/jumper/OpenCL_projects/MatrixTransposition/cat.bmp");
unsigned char *hInputImage = img.getImageDataGrey(imageCols,imageRows);
const int imageElements = imageRows*imageCols;
const size_t imageSize = imageElements*sizeof(unsigned char);
cl_mem bufInputImage = clCreateBuffer(context, CL_MEM_READ_ONLY, imageSize, NULL,&status);
cl_mem bufOutputImage = clCreateBuffer(context, CL_MEM_WRITE_ONLY, imageSize, NULL,&status);
//check(status);
int zero = 0;
status = clEnqueueFillBuffer(cmdQueue, bufOutputImage, &zero,sizeof(int), 0, imageSize, 0, NULL, NULL);
//check(status);
status = clEnqueueWriteBuffer(cmdQueue, bufInputImage, CL_TRUE, 0, imageSize,(void*)hInputImage, 0, NULL, NULL);
//check(status);
char *programSource = readFile("/home/jumper/OpenCL_projects/MatrixTransposition/mine.cl");
size_t programSourceLen = strlen(programSource);
cl_program program = clCreateProgramWithSource(context, 1,(const char**)&programSource, &programSourceLen, &status);
//check(status);
status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
//std::cout<<status<<std::endl;
if (status != CL_SUCCESS) {
printf("cannot build program successfully!\n");
size_t logSize;
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,0, NULL, &logSize);
char *log = (char*)malloc(logSize);
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,logSize, log, NULL);
printf("%s\n", log);
free(log);
exit(-1);
}
cl_kernel kernel;
kernel = clCreateKernel(program, "transposeMatrix", &status);
//check(status);
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &bufInputImage);
status |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &bufOutputImage);
status |= clSetKernelArg(kernel, 2, sizeof(int), &imageCols);
status |= clSetKernelArg(kernel, 3, sizeof(int), &imageRows);
//check(status);
size_t globalWorkSize[1]={1024};
size_t localWorkSize[1]={128};
status = clEnqueueNDRangeKernel(cmdQueue, kernel, 1, NULL,globalWorkSize, localWorkSize, 0, NULL, NULL);
//std::cout<<status<<std::endl;
//check(status);
unsigned char*Outputimg = (unsigned char*)malloc(imageSize);
if (!Outputimg) { exit(-1); }
status = clEnqueueReadBuffer(cmdQueue, bufOutputImage, CL_TRUE, 0,imageSize, Outputimg, 0, NULL, NULL);
Mat dstimg=Mat(imageCols,imageRows,CV_8UC1,Outputimg);
imwrite("dstimg.jpg",dstimg);
SaveGreyimg("/home/jumper/OpenCL_projects/MatrixTransposition/transpose.jpg",Outputimg,imageRows,imageCols);
// use FreeImage to save greyscaled image but failed below!
// FIBITMAP* bitmap=FreeImage_Allocate(128,128,1);
// BYTE *src=new BYTE[128*128*1];
// for(int i=0;i<128*128;i++)
// src[i]=i;
// FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,128,128,128,8,0,0,0,false);
// FreeImage_Save(FIF_PNG,Image,"wdtest.png",0);
// FreeImage_Unload(Image);
// use FreeImage to save color image succeed.
// FIBITMAP* bitmap=FreeImage_Allocate(16,16,3);
// BYTE *src=new BYTE[1024*720*3];
// for(int i=0;i<1024*720;i++){
// src[i*3]=i;
// src[i*3+1]=i;
// src[i*3+2]=200;
// }
// FIBITMAP* Image=FreeImage_ConvertFromRawBits(src,1024,720,1024*3,8*3,0,0,0,false);
// FreeImage_Save(FIF_BMP,Image,"saveimg2.bmp");
// FreeImage_Unload(Image);
std::cout<<FreeImage_GetVersion()<<std::endl;
clReleaseKernel(kernel);
clReleaseProgram(program);
clReleaseCommandQueue(cmdQueue);
clReleaseMemObject(bufInputImage);
clReleaseMemObject(bufOutputImage);
clReleaseContext(context);
free(Outputimg);
free(programSource);
return 0;
}
cl部分我没有动。
结果保存出来了:
果然是FreeImage库的使用那里的问题,用opencv替代就好了。
大神指点后,我终于知道怎么用FreeImage保存灰度图了:http://blog.csdn.net/bob_dong/article/details/64131352 大神很厉害!
/**
* 把缓冲区中的数据保存为灰度图像文件
*/
int store_image(uint8_t *buffer, const char *image_name)
{
int i, j, ret = 0;
// 创建新的位图对象
FIBITMAP *bitmap = FreeImage_Allocate(g_width, g_height, 32);
if (bitmap == NULL) {
printf("alloc bitmap fail\n");
return EXIT_FAILURE;
}
uint8_t *bits = FreeImage_GetBits(bitmap);
for (i = 0; i < g_width * g_height; i++) {
for (j = 0; j < 3; j++)
{
bits[i*4+j] = buffer[i];
}
bits[i*4+3]=255;
}
FreeImage_Save(g_format, bitmap, image_name);
FreeImage_Unload(bitmap);
return ret;
}
原来FreeImage的灰度图也是32位啊也需要跟彩图一样的大小width*height*32,RGB三个通道都是同样的值,相当于将opencv里的单通道的值复制到这三个通道,然后A这个就直接255.。我原来以为它的灰度图跟opencv一样width*height*8就好了 难怪一直异常。