VisionWorks學習之 opencv和VisionWorks Primitives不同點

VisionWorks學習之 opencv和VisionWorks Primitives不同點


下面來看一下opencv和VisionWorks原語的一些不同的地方,算法運算時二者的舍入有些區別,,濾波算法二者對邊界的處理不一樣,顏色轉換使用的顏色標準不一樣,VisionWorks需要指定一下顏色空間。自定義卷積有一些區別,積分圖像visionWorks計算的小一點,不算邊界。然後注意的就是單應矩陣二者差一個轉置。下面詳細來看一下區別。

算術運算

對於 加法、減法、乘法運行,opencv總是使用SATURATE(飽和)策略,VisionWorks使用SATURATE或者WRAP策略。對於乘法操作,OpenCV始終使用ROUND_TO_NEAREST_EVEN(舍入到偶數)舍入策略,而VisionWorks允許在ROUND_TO_NEAREST_EVEN and ROUND_TO_ZERO (舍入到偶數舍入和舍入到零)舍入策略之間進行選擇。

AccumulateWeighted visionworks原語舍入爲零,而cv::addWeighted舍入爲最接近的值。

濾波操作

VisionWorks圖像過濾器(Box3x3、Gaussian3x3等)使用默認VX_BORDER_MODE_UNDEFINED,這意味着邊界上的像素可能計算不準確。opencv總是使用一些邊界外推方法。使用VX_BORDER_MODE_CONSTANT的方法和cv::BORDER_CONSTANT使用一樣的處理方法,使用VX_BORDER_MODE_REPLICATE和cv::BORDER_REPLICATE使用一樣的處理方法,VisionWorks沒有cv::BORDER_REFLECT, cv::BORDER_REFLECT101 以及 cv::BORDER_WRAP.類似項。

顏色轉換

VisionWorks默認使用BT.709顏色空間,而OpenCV使用BT.601如果沒有顯式地將bt.601用於visionworks圖像,則在rgb[x]>Gray轉換中會產生不同的結果。

cv::Mat cv_src = cv::imread(fileName, cv::IMREAD_COLOR);
cv::cvtColor(cv_src, cv_src, cv::COLOR_BGR2RGB);
// OpenCV
cv::Mat cv_dst_original;
cv::cvtColor(cv_src, cv_dst_original, cv::COLOR_RGB2GRAY);
// VisionWorks
cv::Mat cv_dst_nvx(cv_src.size(), CV_8UC1);
vx_image vx_src = nvx_cv::createVXImageFromCVMat(context, cv_src);
vx_image vx_dst = nvx_cv::createVXImageFromCVMat(context, cv_dst_nvx);
vx_enum color_space = VX_COLOR_SPACE_BT601_625;
vxSetImageAttribute(vx_src, VX_IMAGE_ATTRIBUTE_SPACE, &color_space, sizeof(color_space));
vxSetImageAttribute(vx_dst, VX_IMAGE_ATTRIBUTE_SPACE, &color_space, sizeof(color_space));
vxuColorConvert(context, vx_src, vx_dst);
vxReleaseImage(&vx_src);
vxReleaseImage(&vx_dst);

自定義卷積

OpenCV cv::filter2D函數和VisionWorks卷積原語使用不同的公式。
在這裏插入圖片描述
爲了導入使用cv::filter2d的opencv代碼,必須反轉內核並將其轉換爲16s類型:

cv::Mat cv_src = cv::imread(fileName, cv::IMREAD_GRAYSCALE);
cv::Mat cv_kernel = getFilterKernel();
// OpenCV code
cv::Mat cv_dst_original(cv_src.size(), cv_src.type());
cv::filter2D(cv_src, cv_dst_original, CV_8U, cv_kernel, cv::Point(-1, -1), 0, cv::BORDER_REPLICATE);
// VisionWorks code
cv::Mat cv_dst_nvx(cv_src.size(), cv_src.type());
vx_image vx_src = nvx_cv::createVXImageFromCVMat(context, cv_src);
vx_image vx_dst = nvx_cv::createVXImageFromCVMat(context, cv_dst_nvx);
vx_uint32 conv_scale = 1024;
cv::Mat vx_kernel;
cv::flip(cv_kernel, vx_kernel, -1);
vx_kernel.convertTo(vx_kernel, CV_16S, conv_scale);
vx_convolution conv = vxCreateConvolution(context, vx_kernel.cols, vx_kernel.rows);
vxWriteConvolutionCoefficients(conv, vx_kernel.ptr<vx_int16>());
vxSetConvolutionAttribute(conv, VX_CONVOLUTION_ATTRIBUTE_SCALE, &conv_scale, sizeof(conv_scale));
vx_border_t border;
border.mode = VX_BORDER_MODE_REPLICATE;
vxSetContextAttribute(context, VX_CONTEXT_ATTRIBUTE_IMMEDIATE_BORDER_MODE, &border, sizeof(border));
vxuConvolve(context, vx_src, conv, vx_dst);
vxReleaseImage(&vx_src);
vxReleaseImage(&vx_dst);
vxReleaseConvolution(&conv);

圖像積分

在這裏插入圖片描述

圖像扭曲

VisionWorks WarpAffine and WarpPerspective原語的行爲類似於具有cv::WARP_INVERSE_MAP標誌的cv::warpAffine and cv::warpPerspective,要將cv::warpAffine or cv::warpPerspective 調用移植到visionworks,必須對轉換矩陣進行轉置:

// x1 = a * x + b * y + c;
// y1 = d * x + e * y + f;
cv::Mat cv_src = cv::imread(fileName, cv::IMREAD_GRAYSCALE);
// OpenCV
float cv_mat_data[2][3] = {
    {a, b, c},
    {d, e, f}
};
cv::Mat cv_mat(2 /* rows */, 3 /* cols */, CV_32FC1, cv_mat_data);
cv::Mat cv_dst_original;
cv::warpAffine(cv_src, cv_dst_original, cv_mat, cv_src.size(), cv::INTER_LINEAR | cv::WARP_INVERSE_MAP);
// VisionWorks
vx_image vx_src = nvx_cv::createVXImageFromCVMat(context, cv_src);
vx_image vx_dst_1 = vxCreateImage(context, cv_src.cols, cv_src.rows, VX_DF_IMAGE_U8);
vx_float32 vx_mat_data[3][2] = { //這個是cv_mat_data的轉置
    {a, d}, // 'x' coefficients
    {b, e}, // 'y' coefficients
    {c, f}, // 'offsets'
};
vx_matrix vx_mat_1 = vxCreateMatrix(context, VX_TYPE_FLOAT32, 2 /* cols */, 3 /* rows */);
vxWriteMatrix(vx_mat_1, vx_mat_data);
vxuWarpAffine(context, vx_src, vx_mat_1, VX_INTERPOLATION_TYPE_BILINEAR, vx_dst_1);
// or
vx_image vx_dst_2 = vxCreateImage(context, cv_src.cols, cv_src.rows, VX_DF_IMAGE_U8);
vx_matrix vx_mat_2 = nvx_cv::cloneCVMatToVXMatrix(context, cv_mat.t());
vxuWarpAffine(context, vx_src, vx_mat_2, VX_INTERPOLATION_TYPE_BILINEAR, vx_dst_2);

Homography

visionworks FindHomography原語返回Homography matrix,這個矩陣適用於visionworks WarpPerspective原語的格式。所以要在opencv中使用單應矩陣(Homography matrix),必須對其進行轉置:

vx_matrix vx_H = vxCreateMatrix(context, VX_TYPE_FLOAT32, 3, 3);
nvxuFindHomography(context, srcPoints, dstPoints, vx_H, NVX_FIND_HOMOGRAPHY_METHOD_RANSAC,
                   3.0f, 2000, 10, 0.995f, 0.45f, nullptr);
cv::Mat cv_H;
nvx_cv::copyVXMatrixToCVMat(vx_H, cv_H);
cv_H = cv_H.t(); //使用之前需要轉置一下
cv::warpPerspective(cv_src, cv_dst, cv_H, cv_dst.size());

這裏主要還是說的是Opencv和VisionWorks交互的時候注意的事項。後面兩個圖像扭曲和單應矩陣兩者差一個轉置,使用時注意一下即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章