I used CPU version as follows.
vector<float> descriptors;
cv::HOGDescriptor hog(cv::Size(24,32),cv::Size(12,12),cv::Size(4,4),cv::Size(6,6),6);
hog.compute(img, descriptors,cv::Size(8,8), cv::Size(0,0));
My questions is how can get the 'descriptors' using GPU?
I tried the following code. (doesn't work)
cv::gpu::GpuMat gpu_value, gpu_descriptors;
cv::gpu::HOGDescriptor hog_gpu(Size(24,32),Size(12,12),Size(4,4),Size(6,6),6);
gpu_value.upload(img);
hog_gpu.getDescriptors(gpu_value,cv::Size(8,8),gpu_descriptors);
how can I get the 'descriptors' from 'gpu_descriptors'?
Any one can help me to solve this? Many thanks!
You can download gpu_descriptors to CPU memory using gpu::GpuMat memeber function download(), as follows:
Mat cpu_descriptors;
gpu_descriptors.download(cpu_descriptors);
However, the descriptors may be stored differently on the GPU than on CPU, that is cpu_descriptors may not be exactly the same as descriptors computed in your code above. But you can give it a try.
Edit
There doesn't seem to be a method to download descriptors to CPU memory in vector<float> format for gpu::HOGDescriptor. As a side note, I know that you can download descriptors for gpu::SURF_GPU feature detector, using it's member function
void downloadDescriptors(const GpuMat& descriptorsGPU,
vector<float>& descriptors);
which is exactly what you want. But, unfortunately, for some reason this function doesn't exist for cv::gpu::HOGDescriptor. You can attempt to figure out how the data is stored in vector<float> type of descriptors and then try to convert from Mat to vector<float> format.
Related
I'm wondering if there's any way in the cv::cuda namespace to perform pixel operations using GpuMat. Normally I would do
float foo = bar.at<float>(x,y);
However, with GpuMat, I can't find its equivalent. I'm getting a compile error that simply says
"class cv::cuda::GpuMat has no member named at"
GpuMat holds data in GPU memory. Therefore it can't be accessible from host. That's why you didn't find any pixel access operation.
For per-pixel access you should download GpuMat object first, perform the CPU per-pixel operation and upload it back to GPU memory.
Anyway, if you access very few pixels, then you can use some of the cudaMemCopy* functions to download/upload data. In this case you need to calculate address manually from GpuMat::data and GpuMat::step
I am working on a project that needs a lot of OpenCL code. I am using OpenCV's ocl module to develop my project faster but there are some functions not implemented and I will have to write my own OpenCL code.
My question is this: what is the quickest and cheapest way to transfer data from Mat and/or oclMat to a cl_mem array. Re-wording this, is there a good way to transfer or enqueue (clEnqueueWriteBuffer) data from oclMat or Mat?
Currently, I am using a for-loop to read data from Mat (or download from oclMat and then use for-loops) and then enqueuing it. This is turning out to be costly, hence my question.
Thanks to anyone who sees this question :)
I've written a set of interop functions for the Boost.Compute library which ease the use of OpenCL and OpenCV. Take a look at the opencv_copy_mat_to_buffer() function.
There are also functions for copying from a OpenCL buffer back to the host cv::Mat and for copying cv::Mat to OpenCL image2d objects.
Calculate memory bandwidth, achieved in Host-Device interconnections.
If you get ~60% and more of maximal bandwidth, you've nothing to do, memory transfer is as fast as it can be. But if your bandwidth results are lower that 55% - 60% of theoretical maximum, try to use multiple command queues with unblocking operations (don't forget to sync at the end). Also, pay attention on avg image size. Small data transfers usually have big overhead rate.
If your Device uses shared memory, use memory mapping instead of read/write, this may dramatically save time. If Device has it's own memory, apply pinned memory technique, which is well described in NVIDIA OpenCL Best Practices Guide.
The documentation of oclMat states that there is some sort of functionality to the underlying ocl buffer data:
//! pointer to the data(OCL memory object)
uchar *data;
If you have clMat already in the device, you can simply perform a copy buffer from clMat.data to your clBuffer. But you will have to hack a little bit the memory, accessing some private members of the oclMat
Something like:
clEnqueueCopyBuffer(command_queue, (clBuffer *)oclMat.data, dst_buffer, 0, 0, size);
NOTE: Take care with the casting, maybe you have to cast another pointer.
For your comment, it's right. The oclMat can be used as cl_mem(void *) for device, since it was alloced by OpenCL device.
Additionally, you can creat svm memory(for example void* svmdata) at first, and then assign a Mat like: Mat A(rows, cols, CV_32FC1, svmdata).
Now you can process the Mat A between host and device without memory copy.
(PS. The svm memory is the new character of OCL, it can be created by clSVMAlloc).
I am building an image processing application using OpenCV. I am also using the Armadillo library because it has some very neat matrix related functions. The thing is though, in order to use Armadillo functions on cv::Mat I need frequent conversions from cv::Mat to arma::Mat .
To accomplish this I convert the cv::Mat to an arma::Mat using a function like this
arma::Mat cvMat2armaMat(cv::Mat M)
{
copy cv::Mat data to a arma::Mat
return arma::Mat
}
Is there a more efficient way of doing this?
To avoid or reduce copying, you can access the memory used by Armadillo matrices via the .memptr() member function. For example:
mat X(5,6);
double* mem = X.memptr();
Be careful when using the above, as you're not allowed to free the memory yourself (Armadillo will still manage the memory).
Alternatively, you can construct an Armadillo matrix directly from existing memory. For example:
double* data = new double[4*5];
// ... fill data ...
mat X(data, 4, 5, false); // 'false' indicates that no copying is to be done; see docs
In this case you will be responsible for manually managing the memory.
Also bear in mind that Armadillo stores and accesses matrices in column-major order, ie. column 0 is first stored, then column 1, column 2, etc. This is the same as used by MATLAB, LAPACK and BLAS.
I want to copy the data from a cv::Mat to an std::vector. I could obviously go through the entire Mat and copy each value one by one, but I was hoping that there might be an easier way using copyTo, clone, or some sort of pointer manipulation.
Does anyone have any insight on this problem?
Thanks
Assuming your Mat is CV_8UC1, you can do following.
cv::Mat mat(nrows,ncols,CV_8UC1);
...
std::vector<unsigned char> vec;
vec.assign(mat.data,mat.data+nrows*ncols);
For multiple channel image with different pixel type, I think you will be able to easily generalize the code above.
Here is what worked for myself. I had Mat matVec2f of size Nx1, type Vec2f, and a vector of size N. The following code copies the Mat's data to the vector. I believe this should work equally well for data types other than Vec2f.
int N = 10;
vector<Point2f> vec(N);
matVec2f.copyTo(Mat(vec, false));
I am convert a numpy array to a cvMat using fromArray() function. Now when I try to apply Threshold on it I get the below error
OpenCV Error: Unsupported format or combination of formats () in threshold
On checking on stackoverflow I see that it might be an issue with the channel or depth of my image. But I am not sure how can I check that for a cvMat. Could somebody tell me how to check the depth and number of channels for a cvMat in python.
Well, you can't directly get it from a cvMat because cvMats have types instead of depth/channels, so
print mymat.type
returns the type code.
If you want to get the depth and channel number, the easiest way I've found is to generate the IplImage header with cv.GetImage like
print cv.GetImage(mymat).depth,cv.GetImage(mymat).nChannels
I believe cv2 does away with all of that IplImage/cvMat stuff and rolls it all into Mat though.