Vexcl是c++版的opencl,他实现减少opencl的代码量,并且能打印内核内的信息,所以很方便,在github上就可以找到,下面是本人对vexcl的一个应用。
提取将原图像通过opencl变为灰度图像,希望能对需要的对有一点帮助
1.需要github上下载vexcl直接cmake编译安装
2.下载opencv sdk
3.配置好环境
4.完成
本文不能直接运行,部分头文件是测试用的,需要删除,部分函数未删,下次时间充足在补上
#include <iostream>
#include <stdexcept>
#include <vexcl/vexcl.hpp>
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include "ComputeTime.h"
#include "Init_CLBuffer.h"
#include "Dump.h"
//生成高斯核
#define ENumber 2.71828183f
#define PI 3.1415926f
int makeGaussianData(float ** data, int width, int height, float filterRatio) {
int i, j;
float sum = 0.0f;
*data = (float*)malloc(sizeof(float) * width * height);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
float temp = 0.0f;
temp = -1.0f * ((j - width / 2) * (j - width / 2) + (i - height / 2) * (i - height / 2)) / (2.0f * filterRatio * filterRatio);
temp = powf(ENumber, temp);
(*data)[i * width + j] = (1.0f / (2.0f * PI * filterRatio * filterRatio)) * temp;
sum += (*data)[i * width + j];
}
}
printf("sum = %f\n", sum);
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
(*data)[i * width + j] = (*data)[i * width + j] / sum;
}
}
return 0;
}
int main()
{
cv::Mat image;
std::string imageName = "./image/input.jpg";
image = cv::imread(imageName, cv::IMREAD_COLOR); // Read the file
if (!image.data) // Check for invalid input
{
std::cout << "Could not open or find the image" << std::endl;
return false;
}
cv::cvtColor( image, image, CV_RGB2RGBA );
int width = image.cols;
int height = image.rows;
int channel = image.channels();
uchar* mData = image.data;//input buffer data
uchar* nData = (uchar*)malloc(image.rows * image.cols * channel * sizeof(uchar));//output buffer data
std::cout << image.rows << " " << image.cols << " " << image.channels() << " " << sizeof(uchar) << std::endl;
std::cout << image.step << std::endl;
vex::Context ctx(vex::Filter::Type(CL_DEVICE_TYPE_GPU) && vex::Filter::Count(1));
std::cout << ctx << std::endl;
std::vector<vex::backend::kernel> kernel;
dump("srcimage.txt", (char *)mData, width * height * image.channels() * sizeof(uchar));
// Compile and store the kernels for later use.
// Create an OpenCL Image / texture and transfer data to the device
cl::Buffer srcImage;
try {
srcImage = cl::Buffer(ctx.context(0), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(uchar) * image.cols * image.channels() * image.rows, (void*)mData );
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error: " << err.what() << std::endl;
}
// Create a buffer for the result
cl::Buffer clResult = cl::Buffer(ctx.context(0), CL_MEM_WRITE_ONLY, sizeof(float)* image.cols * image.rows * channel);
// Create Gaussian mask
float *GaussData = NULL;
int GaussWidth = 5;
makeGaussianData(&GaussData, 5, 5, 0.8f);
InitCLBuffer init;
// Create buffer for mask and transfer it to the device
cl::Buffer clGaussData = cl::Buffer(ctx.context(0), CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, 5 * 5 * sizeof(float), (void *)GaussData);
ComputeTime ct_init;//calculate timer
ct_init.Begin();
for (uint d = 0; d < ctx.size(); d++)
{
kernel.emplace_back(ctx.queue(d),
VEX_STRINGIZE_SOURCE(
kernel void getBinPerPixel(
__global uchar4 * in,
__global float * binPerPixelImg,
int width)
{
int idx = get_global_id(0);
int idy = get_global_id(1);
uchar4 src = in[idy * width + idx];
binPerPixelImg[idy * width + idx] = (float)(0.2989f*(src.x) + 0.5870f*(src.y) + 0.1140f*(src.z));
}), "getBinPerPixel");
}
std::cout << "time: " << ct_init.End() << "ms" << std::endl;
// Apply the kernels to the vector partitions on each device.
for (uint d = 0; d < ctx.size(); d++)
{
try {
kernel[d].push_arg(srcImage);
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error11: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error11: " << err.what() << std::endl;
}
try {
kernel[d].push_arg(clResult);
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error22: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error22: " << err.what() << std::endl;
}
try {
kernel[d].push_arg(width);
// kernel[d].push_arg(height);
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error33: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error33: " << err.what() << std::endl;
}
try {
// kernel[d].push_arg(width);
// kernel[d].push_arg(height);
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error44: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error44: " << err.what() << std::endl;
}
float sinx = sin(30.0f * PI / 180.0f);
float cosx = cos(30.0f * PI / 180.0f);
try {
// kernel[d].push_arg(sinx);
// kernel[d].push_arg(cosx);
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error55: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error55: " << err.what() << std::endl;
}
try {
kernel[d].config(vex::backend::ndrange(width, height), vex::backend::ndrange(1, 1));
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error1: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error1: " << err.what() << std::endl;
}
try {
kernel[d](ctx.queue(d));
}
catch (const cl::Error &err) {
std::cerr << "OpenCL error2: " << err << std::endl;
}
catch (const std::exception &err) {
std::cerr << "Error2: " << err.what() << std::endl;
}
}
ctx.queue(0).enqueueReadBuffer(clResult, CL_TRUE, 0, sizeof(uchar)* image.cols * channel * image.rows, (void*)nData);
dump("p_image.txt", (char *)nData, width * height * channel * sizeof(float));
ctx.queue(0).flush();
ctx.queue(0).finish();
cv::Mat outputImage(image.rows, image.cols, CV_8UC3, (void*)nData);
if (!outputImage.data) // Check for invalid input
{
std::cout << "Could not open or find the image" << std::endl;
return false;
}
cv::namedWindow("Input image window", cv::WINDOW_AUTOSIZE); // Create a window for display.
cv::imshow("Input image window", image); // Show our image inside it.
cv::namedWindow("Output image window", cv::WINDOW_AUTOSIZE); // Create a window for display.
cv::imshow("Output image window", outputImage); // Show our image inside it.
cv::waitKey(0); // Wait for a keystroke in the window
}