openCV 3.0, openCL and meanShiftFiltering - opencv

Based on the changes in openCV 3.0 and openCL, I can not seem to get pyrMeanShiftFiltering to work using openCL. I know that ocl::meanShiftFiltering was supported in openCV 2.4.10. The two functions below take the same amount of time to execute.
How can I even check which functions in openCV 3.0 are supported under openCL? Any suggestions?
#include <opencv2/core/ocl.hpp> //attempting to use openCL
using namespace cv;
using namespace ocl;
void meanShiftOCL()
{
setUseOpenCL(true)
UMat in, out;
imread("./images/img.png").copyTo(in);
pyrMeanShiftFiltering(in, out, 40, 20, 3);
}
//not using openCL
void meanShift()
{
Mat in, out;
imread("./images/img.png").copyTo(in);
pyrMeanShiftFiltering(in, out, 40, 20, 3);
}

I'm not sure that there is simple way to determine it with given OpenCV binaries, but you can recompile OpenCV yourself with additional define (can be specified in cmake):
CV_OPENCL_RUN_VERBOSE
With this define every function for which OpenCL implementation is available will print to console (stdout) the following message:
<function name>: OpenCL implementation is running
Regarded to your question - currently pyrMeanShiftFiltering doesn't have OpenCL implementation, as I know.

Related

msvc trying to compile cv::Matx<float,3,1> as a 4-element vector

Using MSVC 2017, OpenCV 3.4. Code
typedef Vec3f localcolor;
inline double lensqd(const localcolor & c) {
return c.ddot(c);
}
Get
error C2338: Matx should have at least 4 elements. channels >= 4
note: while compiling class template member function 'cv::Matx<float,3,1>::Matx(_Tp,_Tp,_Tp,_Tp)'
when compiling the ddot function.
The compiler is trying to instantiate a 3-element vector with 4 initializers. I can't see anything in the OCV source code that would make this happen.
So do I file a bug report with MS?
And how do you suggest I get a working build? The code is this way because I sometimes want
typedef Vec4f localcolor;
which BTW compiles without error.
Could you show the ddot function ?
I recently had the same error by attempting to initialize a Vec3f with 4 elements.

Android: linking to opencv results in SIGBUS (signal SIGBUS: illegal alignment) when exception is thrown

I have to work with opencv in an android project. Everything worked fine until I recently had to use c++ exception_ptr as well.
Since then, the use of std::rethrow_exception causes a SIGBUS (signal SIGBUS: illegal alignment).
I created a minimal example to illustrate the problem. The example application only links to opencv 3.4.4 but does not use any opencv function. If you remove the linking to opencv in CMakeLists.txt the app works fine and doesn't crash. If you add it however, the app will crash as soon as the native method triggerException() is called.
In my implementation the example application calls this method if a button is pressed.
native-lib.cpp:
#include <jni.h>
#include <string>
#include <exception>
/*
* code based on: https://en.cppreference.com/w/cpp/error/exception_ptr
*/
std::string handle_eptr2(std::exception_ptr eptr)
{
try {
if (eptr) {
std::rethrow_exception(eptr);
}
} catch (const std::exception &e) {
return "Caught exception \"" + std::string(e.what()) + "\"\n";
}
return "Something went wrong";
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_user_exceptiontest_MainActivity_triggerException(
JNIEnv *env,
jobject /* this */) {
std::exception_ptr eptr;
try {
std::string().at(1); // this generates an std::out_of_range
} catch(...) {
eptr = std::current_exception(); // capture
}
std::string res = handle_eptr2(eptr);
return env->NewStringUTF(res.c_str());
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
set(OPENCV_DIR $ENV{HOME}/lib/OpenCV-android-sdk/sdk )
include_directories(${OPENCV_DIR}/native/jni/include )
add_library( native-lib
SHARED
src/main/cpp/native-lib.cpp)
find_library( log-lib
log)
target_link_libraries(
native-lib
# Removing the following line will make everything work as expected (what() message is returned)
${OPENCV_DIR}/native/libs/${ANDROID_ABI}/libopencv_java3.so # <--- critical line
${log-lib})
build.gradle
To use exceptions and c++17 support, I added the following lines to the configuration that is created by android-studio.
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang',
'-DANDROID_STL=c++_shared'
cppFlags "-std=c++1z -frtti -fexceptions"
}
}
Stacktrace:
<unknown> 0x004c4e47432b2b01
___lldb_unnamed_symbol15856$$libopencv_java3.so 0x0000007f811c4a58
_Unwind_Resume_or_Rethrow 0x0000007f811c4fc8
__cxa_rethrow 0x0000007f81181e50
__gnu_cxx::__verbose_terminate_handler() 0x0000007f811b1580
__cxxabiv1::__terminate(void (*)()) 0x0000007f81181c54
std::terminate() 0x0000007f81181cc0
std::rethrow_exception(std::exception_ptr) 0x0000007f802db2cc
handle_eptr2(std::exception_ptr) native-lib.cpp:35
::Java_com_example_user_exceptiontest_MainActivity_triggerException(JNIEnv *, jobject) native-lib.cpp:58
While searching for a solution I looked at the opencv sources (https://github.com/opencv/opencv/blob/master/modules/core/src/parallel.cpp) and stumbled upon this code snippet:
#ifndef CV__EXCEPTION_PTR
# if defined(__ANDROID__) && defined(ATOMIC_INT_LOCK_FREE) && ATOMIC_INT_LOCK_FREE < 2
# define CV__EXCEPTION_PTR 0 // Not supported, details: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58938
I'd understand if this changes the behavior of opencv, but I don't get how this might influence code that does not use opencv at all.
EDIT: It is also worth mentioning that linking to opencv has no impact if I use this code directly (without jni) in a linux (x86_64) desktop setting (clang, libc++, opencv3.4.4). Thus, my conclusion that it is an android specific problem...
Does anyone has an idea how to solve that issue or what to try next?
Thanks a lot in advance!
Opencv is compiled with gnu runtime while you are using c++ stl. See One STL per app. You will need to either use gnustl (you will need to go back to ndk 15 for that) or build opencv with c++ stl.
In order to build opencv with c++_static you can try to follow comment in opencv bugtracker
cmake -GNinja -DINSTALL_ANDROID_EXAMPLES=ON
-DANDROID_EXAMPLES_WITH_LIBS=ON -DBUILD_EXAMPLES=ON -DBUILD_DOCS=OFF -DWITH_OPENCL=OFF -DWITH_IPP=ON -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake
-DANDROID_TOOLCHAIN=clang "-DANDROID_STL=c++_static" -DANDROID_ABI=x86 -DANDROID_SDK_TARGET=18 ../opencv
Followed by
make && make install

PCL 1.8.1 crash on cloud delete after StatisticalOutliersRemoval

I have an application which is build using several DLL files.
I'm trying to perform PCL's statistical outliers removal using the following code:
PointCloudWithRGBNormalsPtr pclCloud(new PointCloudWithRGBNormals());
ConvertPointCloudToPCL(in_out_cloud /*my own structure which includes xyz, rgb, nx ny nz*/, *pclCloud);
pcl::StatisticalOutlierRemoval<PointXYZRGBNormal> sor;
sor.setInputCloud(pclCloud);
sor.setMeanK(10);
sor.setStddevMulThresh(1.0);
sor.filter(*pclCloud);
ConvertPointCloudToPCL:
static void ConvertPointCloudToPCL(const std::vector<Cloud3DrgbN> &in, PointCloudWithRGBNormals &output)
{
for (auto it = in.begin(); it != in.end(); it++)
{
const Cloud3DrgbN &p3d = *it;;
PointXYZRGBNormal p;
p.x = p3d.x;
p.y = p3d.y;
p.z = p3d.z;
p.normal_x = p3d.nX;
p.normal_y = p3d.nY;
p.normal_z = p3d.nZ;
p.r = p3d.r;
p.g = p3d.g;
p.b = p3d.b;
output.push_back(p);
}
}
For some reason, if I call this function from 1 of my dlls it works as it should. However, there's 1 dll that if I call it from it, when pclCloud goes out of scope, I'm getting an exception from Eigen's Memory.h file at the handmade_aligned_free function
I'm using Windows 10 64-bit, pcl 1.8.1 and Eigen 3.3 (tried 3.3.4, same thing)
Update:
After further digging, I've found that EIGEN_MALLOC_ALREADY_ALIGNED was set to 0 because I'm using AVX2 in my "problematic" DLL. I'm still not sure though why using Eigen's "handmade" aligned malloc/free causes this crash.
There seems to be a known issue (see this) with Eigen, PCL & AVX
Well I found the problem and how to solve it.
It seems that the DLLs that comes with the "All in 1 installer" for windows weren't compiled with AVX/AVX2 support.
When linking these libraries with my own DLLs, the ones that compiled using the AVX, this mismatch caused Eigen to use the different types of allocations and freeing of memory causing the crash.
I compiled PCL from source using AVX2 and linked these library and everything works.
It's worth mentioning that the DLL that worked before now has issues since it doesn't have AVX and PCL now do.

OpenCV3.0 with cuda run time error: getGpuMat is available only for cuda::GpuMat

This is my first time to run OpenCV3.0 with CUDA. The thing is if I run the sample code in the opencv source folder (e.g. test_features2d.cpp), I can get results from CUDA function. However, if I create a standalone program and used CUDA code, it issues run time error (it does not have compiler error):
(I DID USE GPUMAT !!)
OpenCV Error: The function/feature is not implemented (getGpuMat is
available only for center code hereuda::GpuMat and cuda::HostMem) in
getGpuMat, file
/home/lixx2938/opencv-3.0.0/modules/core/src/matrix.cpp, line 1433
terminate called after throwing an instance of 'cv::Exception'
what(): /home/lixx2938/opencv-3.0.0/modules/core/src/matrix.cpp:1433:
error: (-213) getGpuMat is available only for cuda::GpuMat and
cuda::HostMem in function getGpuMat
Here is my trivial partial part of main function:
cv::Ptr<cv::cuda::ORB> orb = cv::cuda::ORB::create(200, 1.2, 4, 31, 0, 2, ORB::HARRIS_SCORE, 31, 20, true);
cv::Ptr<cv::cuda::FastFeatureDetector> fast = cv::cuda::FastFeatureDetector::create(threshold, nonmaxSuppression);
std::vector<cv::KeyPoint> fastkeypoints;
fast->detect(image, fastkeypoints);
std::vector<cv::KeyPoint> keypoints_cuda;
cv::cuda::GpuMat descriptors_cuda;
orb->detectAndCompute(image, noArray(), keypoints_cuda, descriptors2_gpu);
Here is my cmake file
cmake_minimum_required(VERSION 2.8)
project( test )
find_package( OpenCV REQUIRED )
add_executable( test test.cpp )
target_link_libraries( test ${OpenCV_LIBS} )
I think I lose some flags. Does anyone know what I should do to run the opencv code with CUDA?
You need to convert your image to grayscale (because the cuda detectAndCompute method only takes images in grayscale). Afterwards upload it to the GPU. So all in all it should look like that:
cv::Mat image, imageGray;
cv::cuda::GpuMat imageGpu;
cv::cvtColor(image, imageGray, CV_BGR2GRAY);
imageGpu.upload(imageGray);
orb->detectAndComputeAsync(imageGpu, cuda::GpuMat(), keyPointsGpu, descKeyPointsImageGpu);
Hope it helps.
Assuming your image variable is a GpuMat, it could be your std::vector<cv::KeyPoint> keypoints_cuda;. I would try changing this to cv::cuda::GpuMat keypoints_cuda; and testing it out again.

"NV_ENC_ERR_INVALID_VERSION" error while using nvenc encoder

I am using the cuda nvenc encoder to encode an YUV frame. I want to stream the encoded h264 data using RTSP streaming. I need the SPSPPS buffer to do RTSP stream. I am using "nvEncGetSequenceParams" to get the spspps buffer. I have called this function after calling the "nvEncInitializeEncoder" function as expected. I am getting the "NV_ENC_ERR_INVALID_VERSION" error which means I am passing wrong struct to this function. but I have checked multiple times the struct I have passed is correct. I think this can be driver version problem. I have Quadro k5000 GPU. I have tried this on driver version 331.82 and 337.88. Following is the code I am using.
NVENCSTATUS CNvEncoderH264::GetSPSPPSBUffer(char *SPSPPSBuffer)
{
NVENCSTATUS nvSta = NV_ENC_SUCCESS;
uint32_t size = 0;
//m_spspps is of type NV_ENC_SEQUENCE_PARAM_PAYLOAD
m_spspps.inBufferSize = 512;
m_spspps.outSPSPPSPayloadSize = &size;
SET_VER(m_spspps, NV_ENC_INITIALIZE_PARAMS);
m_spspps.spsppsBuffer = SPSPPSBuffer;
nvSta = m_pEncodeAPI->nvEncGetSequenceParams(m_hEncoder,&m_spspps);
return nvSta;
}
You are setting the wrong version macro to the SPS/PPS structure. I don't have my NVIDIA code by hand, so I'll try to Google the right macro but rule of the thumb is that each structure has a specific version macro (ans you are using NV_ENC_INITIALIZE_PARAMS for the SPS/PPS structure which is definitely not right. I assume the type of m_spspps is NV_ENC_SEQUENCE_PARAM_PAYLOAD. So you should initialize it like this:
m_spspps.version = NV_ENC_SEQUENCE_PARAM_PAYLOAD_VER;

Resources