Commit ee8872d5 authored by Miklós Homolya's avatar Miklós Homolya

Qt camera integration

parent 5f69c318
#include "camera.h"
#include <opencv2/imgproc/imgproc.hpp>
Camera camera;
bool Camera::init(int device)
{
capture_.open(device);
if (!capture_.isOpened())
return false;
int camW = 640;
int camH = 480;
capture_.set(CV_CAP_PROP_FRAME_WIDTH, camW);
capture_.set(CV_CAP_PROP_FRAME_HEIGHT, camH);
capture();
width_ = frame_.cols;
height_ = frame_.rows;
return true;
}
void Camera::run()
{
QMutexLocker locker(&mutex);
while (true) { // TODO: never terminates
frameCopied.wait(&mutex);
capture();
emit newFrame();
}
}
void Camera::capture()
{
capture_ >> frame_;
cvtColor(frame_, frame_, CV_BGR2GRAY);
frame_.convertTo(frame_, CV_32F);
frame_ /= 255.f;
}
#ifndef CAMERA_H
#define CAMERA_H
#include <QMutex>
#include <QThread>
#include <QWaitCondition>
#include <opencv2/highgui/highgui.hpp>
class Camera : public QThread {
Q_OBJECT
public:
bool init(int device);
size_t width() const { return width_; }
size_t height() const { return height_; }
float *data() const {
return reinterpret_cast<float *>(frame_.data);
}
QMutex mutex;
QWaitCondition frameCopied;
signals:
void newFrame();
protected:
void run();
private:
cv::VideoCapture capture_;
cv::Mat frame_;
size_t width_, height_;
void capture();
};
extern Camera camera;
#endif // CAMERA_H
#include "glwidget.h" #include "glwidget.h"
#include "camera.h"
#include "kernel.h" #include "kernel.h"
#include <QGLFunctions> #include <QGLFunctions>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cuda_runtime_api.h> #include <cuda_runtime_api.h>
#include <cuda_gl_interop.h> #include <cuda_gl_interop.h>
#include <cstdio> static GLuint pixelsVBO;
static struct cudaGraphicsResource* pixelsVBO_CUDA;
GLuint positionsVBO;
struct cudaGraphicsResource* positionsVBO_CUDA;
GlWidget::GlWidget(QWidget *parent) GlWidget::GlWidget(QWidget *parent)
: QGLWidget(QGLFormat(), parent), func(context()), start(time(NULL)) : QGLWidget(QGLFormat(), parent), gl(context())
{ {
} }
...@@ -25,59 +21,49 @@ GlWidget::~GlWidget() ...@@ -25,59 +21,49 @@ GlWidget::~GlWidget()
QSize GlWidget::sizeHint() const QSize GlWidget::sizeHint() const
{ {
return QSize(640, 480); return QSize(camera.width(), camera.height());
} }
void GlWidget::initializeGL() void GlWidget::initializeGL()
{ {
makeCurrent();
// Explicitly set device 0 // Explicitly set device 0
cudaGLSetGLDevice(0); cudaGLSetGLDevice(0);
// Create buffer object and register it with CUDA // Create buffer object and register it with CUDA
func.glGenBuffers(1, &positionsVBO); gl.glGenBuffers(1, &pixelsVBO);
func.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, positionsVBO); gl.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelsVBO);
size_t size = (size_t)640 * 480 * 4 * sizeof(unsigned char); // TODO size_t size = camera.width() * camera.height() * 4 * sizeof(unsigned char);
func.glBufferData(GL_PIXEL_UNPACK_BUFFER, size, 0, GL_DYNAMIC_DRAW); gl.glBufferData(GL_PIXEL_UNPACK_BUFFER, size, 0, GL_DYNAMIC_DRAW);
//func.glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); // TODO: what is it? cudaGraphicsGLRegisterBuffer(&pixelsVBO_CUDA, pixelsVBO, cudaGraphicsMapFlagsWriteDiscard);
cudaGraphicsGLRegisterBuffer(&positionsVBO_CUDA, positionsVBO, cudaGraphicsMapFlagsWriteDiscard);
} }
void GlWidget::paintGL() void GlWidget::paintGL()
{ {
// Map buffer object for writing from CUDA // Map buffer object for writing from CUDA
unsigned char *positions; void *d_out;
cudaGraphicsMapResources(1, &positionsVBO_CUDA, 0); cudaGraphicsMapResources(1, &pixelsVBO_CUDA, 0);
size_t num_bytes; size_t size;
cudaGraphicsResourceGetMappedPointer((void**)&positions, &num_bytes, positionsVBO_CUDA); cudaGraphicsResourceGetMappedPointer(&d_out, &size, pixelsVBO_CUDA);
float *d_in; size_t inBytes = camera.width() * camera.height() * sizeof(float);
cudaMalloc((void **)&d_in, (size_t)640*480*sizeof(float)); void *d_in;
cudaMalloc(&d_in, inBytes);
extern cv::VideoCapture camera; {
cv::Mat mIn; QMutexLocker locker(&camera.mutex);
camera >> mIn; cudaMemcpy(d_in, camera.data(), inBytes, cudaMemcpyHostToDevice);
printf("width: %d; height: %d;\n", mIn.cols, mIn.rows); cudaDeviceSynchronize();
cvtColor(mIn, mIn, CV_BGR2GRAY); camera.frameCopied.wakeAll();
}
// convert to float representation (opencv loads image values as single bytes by default)
mIn.convertTo(mIn, CV_32F);
// convert range of each channel to [0,1] (opencv default is [0,255])
mIn /= 255.f;
cudaMemcpy(d_in, mIn.data, (size_t)640*480*sizeof(float), cudaMemcpyHostToDevice);
// Execute kernel // Execute kernel
executeKernel(d_in, positions, 640, 480, float(time(0) - start) * 0.1); executeKernel(d_in, d_out, camera.width(), camera.height());
cudaFree(d_in); cudaFree(d_in);
// Unmap buffer object // Unmap buffer object
cudaGraphicsUnmapResources(1, &positionsVBO_CUDA, 0); cudaGraphicsUnmapResources(1, &pixelsVBO_CUDA, 0);
// Render from buffer object // Render from buffer object
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//func.glBindBuffer(GL_ARRAY_BUFFER, positionsVBO); // what is it? glDrawPixels(camera.width(), camera.height(), GL_RGBA, GL_UNSIGNED_BYTE, 0);
glDrawPixels( 640, 480, GL_RGBA, GL_UNSIGNED_BYTE, 0 ); // TODO
} }
...@@ -18,8 +18,7 @@ protected: ...@@ -18,8 +18,7 @@ protected:
void paintGL(); void paintGL();
private: private:
QGLFunctions func; QGLFunctions gl;
time_t start;
}; };
#endif // GLWIDGET_H #endif // GLWIDGET_H
...@@ -5,8 +5,8 @@ TARGET = hello-opengl ...@@ -5,8 +5,8 @@ TARGET = hello-opengl
TEMPLATE = app TEMPLATE = app
SOURCES += main.cpp glwidget.cpp SOURCES += main.cpp glwidget.cpp camera.cpp
HEADERS += glwidget.h kernel.h HEADERS += glwidget.h kernel.h camera.h
CUDA_SOURCES += kernel.cu CUDA_SOURCES += kernel.cu
......
#include "kernel.h" #include "kernel.h"
__global__ void createVertices(float *in, uchar4* positions, int width, int height) __global__ void createVertices(float *in, uchar4* pixel, int w, int h)
{ {
unsigned int x = blockIdx.x * blockDim.x + threadIdx.x; unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
unsigned int y = blockIdx.y * blockDim.y + threadIdx.y; unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;
unsigned char intensity = roundf(255 * in[y * width + x]); unsigned char intensity = roundf(255 * in[y * w + x]);
// Write positions // Write positions
positions[y * width + x].x = intensity; size_t i = x + w*(h-1 - y);
positions[y * width + x].y = intensity; pixel[i].x = intensity;
positions[y * width + x].z = intensity; pixel[i].y = intensity;
positions[y * width + x].w = 255; pixel[i].z = intensity;
pixel[i].w = 255;
} }
void executeKernel(float *d_in, void *positions_, int width, int height, float time) void executeKernel(void *d_in, void *d_out, size_t w, size_t h)
{ {
uchar4 *positions = (uchar4 *)positions_; float *in = reinterpret_cast<float *>(d_in);
uchar4 *pixel = reinterpret_cast<uchar4 *>(d_out);
dim3 dimBlock(16, 16, 1); dim3 dimBlock(16, 16, 1);
dim3 dimGrid(width / dimBlock.x, height / dimBlock.y, 1); dim3 dimGrid(w / dimBlock.x, h / dimBlock.y, 1);
createVertices<<<dimGrid, dimBlock>>>(d_in, positions, width, height); createVertices<<<dimGrid, dimBlock>>>(in, pixel, w, h);
} }
#ifndef _KERNEL_H #ifndef KERNEL_H
#define _KERNEL_H #define KERNEL_H
extern "C" void executeKernel(float *d_in, void *positions_, int width, int height, float time); extern "C" void executeKernel(void *d_in, void *d_out, size_t width, size_t height);
#endif // _KERNEL_H #endif // KERNEL_H
#include <iostream> #include "camera.h"
#include <QApplication>
#include <opencv2/highgui/highgui.hpp>
#include "glwidget.h" #include "glwidget.h"
cv::VideoCapture camera; #include <iostream>
#include <QApplication>
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
GlWidget w;
// Init camera // Init camera
camera.open(0); if(!camera.init(0)) {
if(!camera.isOpened()) {
std::cerr << "ERROR: Could not open camera" << std::endl; std::cerr << "ERROR: Could not open camera" << std::endl;
return 1; return 1;
} }
int camW = 640;
int camH = 480;
camera.set(CV_CAP_PROP_FRAME_WIDTH,camW);
camera.set(CV_CAP_PROP_FRAME_HEIGHT,camH);
GlWidget w; QObject::connect(&camera, SIGNAL(newFrame()), &w, SLOT(updateGL()));
camera.start();
w.show(); w.show();
return app.exec(); return app.exec();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment