/*
* Copyright (C) 2011-2012 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bytedeco.javacv;
import com.jogamp.opencl.CLCommandQueue;
import com.jogamp.opencl.CLBuffer;
import com.jogamp.opencl.CLContext;
import com.jogamp.opencl.CLDevice;
import com.jogamp.opencl.CLEventList;
import com.jogamp.opencl.CLImage2d;
import com.jogamp.opencl.CLImageFormat;
import com.jogamp.opencl.CLImageFormat.ChannelOrder;
import com.jogamp.opencl.CLImageFormat.ChannelType;
import com.jogamp.opencl.CLKernel;
import com.jogamp.opencl.CLMemory;
import com.jogamp.opencl.CLObject;
import com.jogamp.opencl.CLPlatform;
import com.jogamp.opencl.CLProgram;
import com.jogamp.opencl.CLProgram.CompilerOptions;
import com.jogamp.opencl.gl.CLGLContext;
import com.jogamp.opencl.gl.CLGLImage2d;
import com.jogamp.opencl.gl.CLGLObject;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesImmutable;
import com.jogamp.opengl.GLContext;
import com.jogamp.opengl.GLDrawableFactory;
import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.glu.GLU;
import java.io.InputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.nio.ByteBuffer;
import java.util.Vector;
import java.util.logging.Logger;
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.BytePointer;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;
/**
*
* @author Samuel Audet
*
* To make NVIDIA drivers happy, we may need to limit the maximum
* heap memory size of Java to 1 GB, by defining something like
* export _JAVA_OPTIONS=-Xmx1G
*
*/
public class JavaCVCL {
public JavaCVCL(CLContext context) {
this(context, context.getDevices()[0]);
}
public JavaCVCL(CLContext context, CLDevice device) {
// this.pbuffer = null;
this.context = context;
this.glu = context instanceof CLGLContext ? new GLU() : null;
this.commandQueue = device.createCommandQueue(/*Mode.PROFILING_MODE*/);
CLKernel[] kernels = buildKernels(fastCompilerOptions, "JavaCV.cl", "pyrDown", "remap", "remapBayer");
this.pyrDownKernel = kernels[0];
this.remapKernel = kernels[1];
this.remapBayerKernel = kernels[2];
}
public static GLCapabilities getDefaultGLCapabilities(GLProfile profile) {
GLCapabilities caps = new GLCapabilities(profile != null ? profile : GLProfile.getDefault());
// Without line below, there is an error on Windows.
caps.setDoubleBuffered(false);
return caps;
}
public JavaCVCL() {
this(false);
}
public JavaCVCL(boolean createPbuffer) {
this(createPbuffer ? getDefaultGLCapabilities(null) : null, null, null);
}
public JavaCVCL(GLContext shareWith) {
this(getDefaultGLCapabilities(shareWith == null ? null :
shareWith.getGLDrawable().getGLProfile()), shareWith, null);
}
public JavaCVCL(GLCapabilitiesImmutable caps, GLContext shareWith, CLDevice device) {
// GLPbuffer pbuffer = null;
// if (caps != null) {
// GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile());
// if (factory.canCreateGLPbuffer(null, caps.getGLProfile())) {
// try {
// // makes a new buffer
// pbuffer = factory.createGLPbuffer(null, caps, null, 32, 32, shareWith);
// // required for drawing to the buffer
// pbuffer.createContext(shareWith).makeCurrent();
// } catch (GLException e) {
// logger.warning("Could not create PBuffer: " + e);
// }
// } else {
// logger.warning("OpenGL implementation does not support PBuffers.");
// }
// }
// this.pbuffer = pbuffer;
GLContext glContext = GLContext.getCurrent();
if (device == null && glContext != null) {
// woohoo! we have a GLContext
// find gl compatible device
CLDevice[] devices = CLPlatform.getDefault().listCLDevices();
for (CLDevice d : devices) {
if(d.isGLMemorySharingSupported()) {
device = d;
break;
}
}
// if(null==device) {
// throw new RuntimeException("couldn't find any CL/GL memory sharing devices ..");
// }
}
if (glContext != null && device != null) {
// create OpenCL context before creating any OpenGL objects
// you want to share with OpenCL (AMD driver requirement)
context = CLGLContext.create(glContext, device);
glu = GLU.createGLU();
} else if (device != null) {
context = CLContext.create(device);
glu = null;
} else {
// find a CL implementation
//CLPlatform platform = CLPlatform.getDefault(/*type(CPU)*/);
context = CLContext.create(/*platform.getMaxFlopsDevice()*/);
device = context.getDevices()[0];
glu = null;
}
// creade a command queue with benchmarking flag set
commandQueue = device.createCommandQueue(/*Mode.PROFILING_MODE*/);
CLKernel[] kernels = buildKernels(fastCompilerOptions, "JavaCV.cl", "pyrDown", "remap", "remapBayer");
this.pyrDownKernel = kernels[0];
this.remapKernel = kernels[1];
this.remapBayerKernel = kernels[2];
}
public void release() {
if (!context.isReleased()) {
context.release();
// if (pbuffer != null) {
// pbuffer.getContext().makeCurrent();
// pbuffer.getContext().release();
// pbuffer.getContext().destroy();
// pbuffer.destroy();
// }
}
}
@Override protected void finalize() throws Throwable {
super.finalize();
release();
}
public static final String fastCompilerOptions = // "-cl-nv-verbose " +
CompilerOptions.FAST_RELAXED_MATH + " " + CompilerOptions.ENABLE_MAD;
private static final Logger logger = Logger.getLogger(JavaCVCL.class.getName());
// private final GLPbuffer pbuffer;
private final CLContext context;
private final CLCommandQueue commandQueue;
private final GLU glu;
private final CLKernel pyrDownKernel, remapKernel, remapBayerKernel;
public CLContext getCLContext() {
return context;
}
public CLCommandQueue getCLCommandQueue() {
return commandQueue;
}
public CLGLContext getCLGLContext() {
return context instanceof CLGLContext ? (CLGLContext)context : null;
}
public GLContext getGLContext() {
return context instanceof CLGLContext ? ((CLGLContext)context).getGLContext() : null;
}
public GL getGL() {
GLContext glContext = getGLContext();
return glContext != null ? glContext.getGL() : null;
}
public GL2 getGL2() {
GL gl = getGL();
return gl != null ? gl.getGL2() : null;
}
public GLU getGLU() {
return glu;
}
public CLKernel buildKernel(String resourceNames, String kernelName) {
return buildKernels(fastCompilerOptions, Loader.getCallerClass(2), resourceNames, kernelName)[0];
}
public CLKernel buildKernel(String compilerOptions, String resourceNames, String kernelName) {
return buildKernels(compilerOptions, Loader.getCallerClass(2), resourceNames, kernelName)[0];
}
public CLKernel[] buildKernels(String compilerOptions, String resourceNames, String ... kernelNames) {
return buildKernels(compilerOptions, Loader.getCallerClass(2), resourceNames, kernelNames);
}
public CLKernel[] buildKernels(String compilerOptions, Class resourceClass, String resourceNames, String ... kernelNames) {
try {
//load and compile program for the chosen device
InputStream s;
String[] a = resourceNames.split(":");
if (a.length == 1) {
s = resourceClass.getResourceAsStream(a[0]);
} else {
Vector<InputStream> vs = new Vector<InputStream>(a.length);
for (String name : a) {
vs.addElement(resourceClass.getResourceAsStream(name));
}
s = new SequenceInputStream(vs.elements());
}
CLProgram program = context.createProgram(s);
//System.out.println("Building " + resourceNames + "...");
program.build(compilerOptions);
//System.out.println(program.getBuildLog());
assert program.isExecutable();
// create kernel and set function parameters
CLKernel[] kernels = new CLKernel[kernelNames.length];
for (int i = 0; i < kernelNames.length; i++) {
kernels[i] = program.createCLKernel(kernelNames[i]);
}
return kernels;
} catch(IOException ex) {
throw (Error)new LinkageError(ex.toString()).initCause(ex);
}
}
public CLImage2d createCLImageFrom(IplImage image, CLImage2d.Mem ... flags) {
int width = image.width();
int height = image.height();
int pitch = image.widthStep();
ByteBuffer buffer = image.getByteBuffer();
ChannelOrder order = null;
ChannelType type = null;
int size = 0;
switch (image.depth()) {
case IPL_DEPTH_8S: type = ChannelType.SNORM_INT8; size = 1; break;
case IPL_DEPTH_8U: type = ChannelType.UNORM_INT8; size = 1; break;
case IPL_DEPTH_16S: type = ChannelType.SNORM_INT16; size = 2; break;
case IPL_DEPTH_16U: type = ChannelType.UNORM_INT16; size = 2; break;
case IPL_DEPTH_32S: type = ChannelType.SIGNED_INT32; size = 4; break;
case IPL_DEPTH_32F: type = ChannelType.FLOAT; size = 4; break;
default: assert false;
}
switch (image.nChannels()) {
case 1: order = ChannelOrder.LUMINANCE; break;
case 2: order = ChannelOrder.RG; size *= 2; break;
case 3: order = ChannelOrder.RGB; size *= 3; break;
case 4: order = ChannelOrder.RGBA; size *= 4; break;
default: assert false;
}
// NVIDIA drivers do not like it when width != pitch/size
if (width != pitch/size) {
width = pitch/size;
}
CLImageFormat format = new CLImageFormat(order, type);
return context.createImage2d(buffer, width, height, /*pitch,*/ format, flags);
}
public CLGLImage2d createCLGLImageFrom(IplImage image, CLImage2d.Mem ... flags) {
GL2 gl = getGL2();
if (gl == null) {
return null;
}
int width = image.width();
int height = image.height();
int pitch = image.widthStep();
//ByteBuffer buffer = image.getByteBuffer();
int format = 0;
int size = 0;
switch (image.nChannels()) {
case 1:
switch (image.depth()) {
case IPL_DEPTH_8S: format = GL2.GL_LUMINANCE8_SNORM; size = 1; break;
case IPL_DEPTH_8U: format = GL2.GL_LUMINANCE8; size = 1; break;
case IPL_DEPTH_16S: format = GL2.GL_LUMINANCE16_SNORM; size = 2; break;
case IPL_DEPTH_16U: format = GL2.GL_LUMINANCE16; size = 2; break;
case IPL_DEPTH_32S: format = GL2.GL_LUMINANCE32I; size = 4; break;
case IPL_DEPTH_32F: format = GL2.GL_LUMINANCE32F; size = 4; break;
default: assert false;
}
break;
case 2:
switch (image.depth()) {
case IPL_DEPTH_8S: format = GL2.GL_RG8_SNORM; size = 2; break;
case IPL_DEPTH_8U: format = GL2.GL_RG8; size = 2; break;
case IPL_DEPTH_16S: format = GL2.GL_RG16_SNORM; size = 4; break;
case IPL_DEPTH_16U: format = GL2.GL_RG16; size = 4; break;
case IPL_DEPTH_32S: format = GL2.GL_RG32I; size = 8; break;
case IPL_DEPTH_32F: format = GL2.GL_RG32F; size = 8; break;
default: assert false;
}
break;
case 3:
switch (image.depth()) {
case IPL_DEPTH_8S: format = GL2.GL_RGB8_SNORM; size = 3; break;
case IPL_DEPTH_8U: format = GL2.GL_RGB8; size = 3; break;
case IPL_DEPTH_16S: format = GL2.GL_RGB16_SNORM; size = 6; break;
case IPL_DEPTH_16U: format = GL2.GL_RGB16; size = 6; break;
case IPL_DEPTH_32S: format = GL2.GL_RGB32I; size = 12; break;
case IPL_DEPTH_32F: format = GL2.GL_RGB32F; size = 12; break;
default: assert false;
}
break;
case 4:
switch (image.depth()) {
case IPL_DEPTH_8S: format = GL2.GL_RGBA8_SNORM; size = 4; break;
case IPL_DEPTH_8U: format = GL2.GL_RGBA8; size = 4; break;
case IPL_DEPTH_16S: format = GL2.GL_RGBA16_SNORM; size = 8; break;
case IPL_DEPTH_16U: format = GL2.GL_RGBA16; size = 8; break;
case IPL_DEPTH_32S: format = GL2.GL_RGBA32I; size = 16; break;
case IPL_DEPTH_32F: format = GL2.GL_RGBA32F; size = 16; break;
default: assert false;
}
break;
default: assert false;
}
// NVIDIA drivers do not like it when width != pitch/size
if (width != pitch/size) {
width = pitch/size;
}
int[] renderBuffer = new int[1];
gl.glGenRenderbuffers(1, renderBuffer, 0);
gl.glBindRenderbuffer(GL2.GL_RENDERBUFFER, renderBuffer[0]);
gl.glRenderbufferStorage(GL2.GL_RENDERBUFFER, format, width, height);
return getCLGLContext().createFromGLRenderbuffer(renderBuffer[0], flags);
}
public void releaseCLGLImage(CLGLImage2d image) {
image.release();
getGL2().glDeleteRenderbuffers(1, new int[] { image.getGLObjectID() }, 0);
}
@SuppressWarnings("unchecked")
public CLBuffer createPinnedBuffer(int size) {
// as per NVIDIA's OpenCL Best Practices Guide
CLBuffer pinnedBuffer = context.createBuffer(size, CLMemory.Mem.ALLOCATE_BUFFER);
ByteBuffer byteBuffer = commandQueue.putMapBuffer(pinnedBuffer, CLMemory.Map.READ_WRITE, true);
pinnedBuffer.use(byteBuffer);
return pinnedBuffer;
}
class PinnedIplImage extends IplImage {
PinnedIplImage(int width, int height, int depth, int channels) {
super(cvCreateImageHeader(new CvSize().width(width).height(height), depth, channels));
pinnedBuffer = createPinnedBuffer(imageSize());
imageData(new BytePointer(getByteBuffer()));
}
final CLBuffer pinnedBuffer;
public CLBuffer getCLBuffer() {
return pinnedBuffer;
}
@Override public ByteBuffer getByteBuffer() {
return (ByteBuffer)pinnedBuffer.getBuffer();
}
@Override public void release() {
commandQueue.putUnmapMemory(pinnedBuffer, getByteBuffer());
pinnedBuffer.release();
cvReleaseImageHeader(this);
}
}
public IplImage createPinnedIplImage(int width, int height, int depth, int channels) {
return new PinnedIplImage(width, height, depth, channels);
}
public IplImage createIplImageFrom(CLImage2d image) {
int width = image.width;
int height = image.height;
CLImageFormat format = image.getFormat();
ChannelOrder order = format.getImageChannelOrder();
ChannelType type = format.getImageChannelDataType();
int depth = 0, channels = 0;
switch (order) {
case R:
case A:
case INTENSITY:
case LUMINANCE:
channels = 1;
break;
case Rx:
case RG:
case RA:
channels = 2;
break;
case RGx:
case RGB:
channels = 3;
break;
case RGBx:
case RGBA:
case ARGB:
case BGRA:
channels = 4;
break;
default: assert false;
}
switch (type) {
case SIGNED_INT8:
case SNORM_INT8: depth = IPL_DEPTH_8S; break;
case UNSIGNED_INT8:
case UNORM_INT8: depth = IPL_DEPTH_8U; break;
case SIGNED_INT16:
case SNORM_INT16: depth = IPL_DEPTH_16S; break;
case UNSIGNED_INT16:
case UNORM_INT16: depth = IPL_DEPTH_16U; break;
case UNSIGNED_INT32:
case SIGNED_INT32: depth = IPL_DEPTH_32S; break;
case FLOAT: depth = IPL_DEPTH_32F; break;
case HALF_FLOAT:
case UNORM_SHORT_565:
case UNORM_SHORT_555:
case UNORM_INT_101010:
default: assert false;
}
return IplImage.create(width, height, depth, channels);
//return createPinnedIplImage(width, height, depth, channels);
}
@SuppressWarnings("unchecked")
public IplImage readImage(CLImage2d clImg, IplImage iplImage, boolean blocking) {
if (iplImage == null) {
iplImage = createIplImageFrom(clImg);
}
int x = 0, y = 0;
int width = clImg.width;
int height = clImg.height;
int pitch = iplImage.widthStep();
ByteBuffer buffer = iplImage.getByteBuffer();
IplROI roi = iplImage.roi();
if (roi != null) {
x = roi.xOffset();
y = roi.yOffset();
width = roi.width();
height = roi.height();
int pixelSize = iplImage.nChannels()*((iplImage.depth()&~IPL_DEPTH_SIGN)/8);
buffer = iplImage.getByteBuffer(y*pitch + x*pixelSize);
}
clImg.use(buffer);
commandQueue.putReadImage(clImg, pitch, x, y, width, height, blocking);
return iplImage;
}
@SuppressWarnings("unchecked")
public CLImage2d writeImage(CLImage2d clImg, IplImage iplImage, boolean blocking) {
if (clImg == null) {
clImg = createCLImageFrom(iplImage);
}
int x = 0, y = 0;
int width = iplImage.width();
int height = iplImage.height();
int pitch = iplImage.widthStep();
ByteBuffer buffer = iplImage.getByteBuffer();
IplROI roi = iplImage.roi();
if (roi != null) {
x = roi.xOffset();
y = roi.yOffset();
width = roi.width();
height = roi.height();
int pixelSize = iplImage.nChannels()*((iplImage.depth()&~IPL_DEPTH_SIGN)/8);
buffer = iplImage.getByteBuffer(y*pitch + x*pixelSize);
}
clImg.use(buffer);
commandQueue.putWriteImage(clImg, pitch, x, y, width, height, blocking);
return clImg;
}
public void acquireGLObject(CLObject object) {
if (object instanceof CLGLObject) {
commandQueue.putAcquireGLObject((CLGLObject)object);
}
}
public void releaseGLObject(CLObject object) {
if (object instanceof CLGLObject) {
commandQueue.putReleaseGLObject((CLGLObject)object);
}
}
public void readBuffer(CLBuffer<?> buffer, boolean blocking) {
commandQueue.putReadBuffer(buffer, blocking);
}
public void writeBuffer(CLBuffer<?> buffer, boolean blocking) {
commandQueue.putWriteBuffer(buffer, blocking);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkSizeX, long localWorkSizeX) {
commandQueue.put1DRangeKernel(kernel,
globalWorkOffsetX, globalWorkSizeX, localWorkSizeX);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkSizeX, long localWorkSizeX, CLEventList events) {
commandQueue.put1DRangeKernel(kernel,
globalWorkOffsetX, globalWorkSizeX, localWorkSizeX, events);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkSizeX, long localWorkSizeX,
CLEventList condition, CLEventList events) {
commandQueue.put1DRangeKernel(kernel,
globalWorkOffsetX, globalWorkSizeX, localWorkSizeX, condition, events);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY,
long globalWorkSizeX, long globalWorkSizeY,
long localWorkSizeX, long localWorkSizeY) {
commandQueue.put2DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY,
globalWorkSizeX, globalWorkSizeY,
localWorkSizeX, localWorkSizeY);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY,
long globalWorkSizeX, long globalWorkSizeY,
long localWorkSizeX, long localWorkSizeY, CLEventList events) {
commandQueue.put2DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY,
globalWorkSizeX, globalWorkSizeY,
localWorkSizeX, localWorkSizeY, events);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY,
long globalWorkSizeX, long globalWorkSizeY,
long localWorkSizeX, long localWorkSizeY,
CLEventList condition, CLEventList events) {
commandQueue.put2DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY,
globalWorkSizeX, globalWorkSizeY,
localWorkSizeX, localWorkSizeY, condition, events);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY, long globalWorkOffsetZ,
long globalWorkSizeX, long globalWorkSizeY, long globalWorkSizeZ,
long localWorkSizeX, long localWorkSizeY, long localWorkSizeZ) {
commandQueue.put3DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY, globalWorkOffsetZ,
globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
localWorkSizeX, localWorkSizeY, localWorkSizeZ);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY, long globalWorkOffsetZ,
long globalWorkSizeX, long globalWorkSizeY, long globalWorkSizeZ,
long localWorkSizeX, long localWorkSizeY, long localWorkSizeZ, CLEventList events) {
commandQueue.put3DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY, globalWorkOffsetZ,
globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
localWorkSizeX, localWorkSizeY, localWorkSizeZ, events);
}
public void executeKernel(CLKernel kernel,
long globalWorkOffsetX, long globalWorkOffsetY, long globalWorkOffsetZ,
long globalWorkSizeX, long globalWorkSizeY, long globalWorkSizeZ,
long localWorkSizeX, long localWorkSizeY, long localWorkSizeZ,
CLEventList condition, CLEventList events) {
commandQueue.put3DRangeKernel(kernel,
globalWorkOffsetX, globalWorkOffsetY, globalWorkOffsetZ,
globalWorkSizeX, globalWorkSizeY, globalWorkSizeZ,
localWorkSizeX, localWorkSizeY, localWorkSizeZ, condition, events);
}
public void finish() {
commandQueue.finish();
}
public void flush() {
commandQueue.flush();
}
public static int alignCeil(int x, int n) {
return (x + n-1)/n*n;
}
public static int alignFloor(int x, int n) {
return x/n*n;
}
public void pyrDown(CLImage2d srcImg, CLImage2d dstImg) {
CLEventList list = null;//new CLEventList(1);
pyrDownKernel.putArg(srcImg).putArg(dstImg).rewind();
executeKernel(pyrDownKernel, 0, 0, alignCeil(dstImg.width, 2), alignCeil(dstImg.height, 64), 2, 64, list); // execute program
// finish();
// CLEvent event = list.getEvent(0);
// System.out.println("pyrDown: " + (event.getProfilingInfo(CLEvent.ProfilingCommand.END) -
// event.getProfilingInfo(CLEvent.ProfilingCommand.START))/1000000.0);
}
public void remap(CLImage2d srcImg, CLImage2d dstImg, CLImage2d mapxImg, CLImage2d mapyImg) {
remap(srcImg, dstImg, mapxImg, mapyImg, -1L);
}
public void remap(CLImage2d srcImg, CLImage2d dstImg, CLImage2d mapxImg, CLImage2d mapyImg, long sensorPattern) {
CLEventList list = null;//new CLEventList(1);
CLKernel kernel;
if (sensorPattern != -1L) {
kernel = remapBayerKernel.putArg(srcImg).putArg(dstImg).putArg(mapxImg).putArg(mapyImg).putArg(sensorPattern).rewind();
} else {
kernel = remapKernel.putArg(srcImg).putArg(dstImg).putArg(mapxImg).putArg(mapyImg).rewind();
}
executeKernel(kernel, 0, 0, alignCeil(dstImg.width, 2), alignCeil(dstImg.height, 64), 2, 64, list); // execute program
// finish();
// CLEvent event = list.getEvent(0);
// System.out.println("remap: " + (event.getProfilingInfo(CLEvent.ProfilingCommand.END) -
// event.getProfilingInfo(CLEvent.ProfilingCommand.START))/1000000.0);
}
public static void main(String[] args) {
JavaCVCL context = new JavaCVCL();
CLImageFormat[] formats = context.getCLContext().getSupportedImage2dFormats();
for (CLImageFormat f : formats) {
System.out.println(f);
}
CameraDevice camera = new CameraDevice("Camera");
camera.imageWidth = 1280;
camera.imageHeight = 960;
camera.cameraMatrix = CvMat.create(3, 3);
double f = camera.imageWidth*2.5;
camera.cameraMatrix.put(f, 0.0, camera.imageWidth /2,
0.0, f, camera.imageHeight/2,
0.0, 0.0, 1);
camera.R = CvMat.create(3, 3);
cvSetIdentity(camera.R);
camera.T = CvMat.create(3, 1);
cvSetZero(camera.T);
camera.distortionCoeffs = CvMat.create(1, 4);
cvSetZero(camera.distortionCoeffs);
camera.distortionCoeffs.put(0.2);
camera.colorMixingMatrix = CvMat.create(3, 3);
cvSetIdentity(camera.colorMixingMatrix);
IplImage srcImg = cvLoadImageRGBA(args[0]);
//IplImage dstImg = srcImg.clone();
IplImage downDst = IplImage.create(srcImg.width()/2, srcImg.height()/2, IPL_DEPTH_8U /*IPL_DEPTH_32F*/, 4);
camera.setFixedPointMaps(false);
camera.setMapsPyramidLevel(1);
IplImage mapxImg = camera.getUndistortMap1();
IplImage mapyImg = camera.getUndistortMap2();
long start = System.nanoTime();
cvRemap(srcImg, downDst, mapxImg, mapyImg, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, CvScalar.ZERO);
System.out.println("cvRemap: " + (System.nanoTime()-start)/1000000.0);
cvSaveImage("/tmp/opencv.png", downDst);
CLImage2d src = context.createCLImageFrom(srcImg);
// CLImage2d dst = context.createCLImageFrom(dstImg);
CLImage2d dst = context.createCLImageFrom(downDst);
CLImage2d mapx = context.createCLImageFrom(mapxImg);
CLImage2d mapy = context.createCLImageFrom(mapyImg);
context.writeImage(src, srcImg, false);
context.writeImage(mapx, mapxImg, false);
context.writeImage(mapy, mapyImg, false);
//context.pyrDown(src, dst);
context.remap(src, dst, mapx, mapy);
context.readImage(dst, downDst, true);
//cvConvertScale(downDst, downDst, 255, 0);
cvSaveImage("/tmp/javacvcl.png", downDst);
context.release();
System.exit(0);
}
}