首页 > 解决方案 > 具有颜色之间依赖关系的颜色过滤

问题描述

我目前的目标是制作一个滤色器(可能是阈值),为具有以下关系的区域创建一个蒙版:

B < G

G > 128

R > 1.5 * G

我已经创建了这样的算法,但它会遍历图像的每个像素并手动检测是否满足这些条件。哪个 - 正如您可能已经猜到的那样 - 相当慢。

在之前的机器 (NUCi7) 上,生成的程序可以达到大约 6-10 FPS,但它完全在 CPU 上运行。现在我切换到 Jetson Xavier NX 来看看 GPU 加速的 OpenCV。目前我正在寻找一个或几个功能,可以以一种有效的方式实现这些条件。

我不是想找到最有效的方法,如果一开始就太复杂的话。但是我测试了一些对象跟踪算法,这些算法在 40+ FPS 和 HD2K 图像上的工作就像一个魅力,所以我希望有一种方法可以完成这项工作并最终达到 40+/60+ FPS。

inRange函数这样的东西会很棒,但对于 GPU-OpenCV 来说似乎还不存在。也许有一种聪明的方法可以用thresholds来实现它,但到目前为止我只是用静态值找到它。

.

https://docs.opencv.org/2.4/modules/gpu/doc/image_processing.html

image.forEach<Pixel>
        (
            [&](Pixel &pixel, const int * position) -> void
            {
                if (pixel.z > 1.5 * pixel.y &&
                    (pixel.y > pixel.x) && 
                    pixel.y > 128){
                        pixel.z = 255;
                        pixel.y = 255;
                        pixel.x = 255;
                } else {
                        pixel.z = 0;
                        pixel.y = 0;
                        pixel.x = 0;
                }
            }
        );

代码基本上就是我想从这里开始的代码。从上面应用 foreach 循环。

实际的当前代码是这个:

while (viewer.isAvailable()) {
        // Grab images
        if (zed.grab(runtime_parameters) == ERROR_CODE::SUCCESS) {

            // Retrieve left image
            zed.retrieveImage(image_zed, VIEW::LEFT, MEM::GPU,new_image_size);
            cv::Mat image_ocv = slMat2cvMat(image_zed);

            // <!-- Everything here is a test to insert a custom 3D-Bounding box into the live-image
            sl::ObjectData newObject;
            sl::ObjectData refObject;
            std::cout << "\n\nNew Loop" << endl;

            // Retrieve Detected Human Bodies
            zed.retrieveObjects(objects, objectTracker_parameters_rt);

            int id = 42;
            sl::float3 newPosition = {-.1,.1,-0.5};
            sl::float3 newVelocity = {.0,.0,.0};
            
            std::vector<sl::float3> newBounding_box;
            sl::float3 pOri = {looper[0],looper[1],looper[2]};
            sl::float3 pDim = {0.25,0.25,0.25};
            sl::float3 p0 = {pOri[0]-pDim[0]/2,pOri[1]-pDim[1]/2,pOri[2]-pDim[2]/2};
            sl::float3 p1 = {pOri[0]-pDim[0]/2,pOri[1]-pDim[1]/2,pOri[2]+pDim[2]/2};
            sl::float3 p2 = {pOri[0]+pDim[0]/2,pOri[1]-pDim[1]/2,pOri[2]+pDim[2]/2};
            sl::float3 p3 = {pOri[0]+pDim[0]/2,pOri[1]-pDim[1]/2,pOri[2]-pDim[2]/2};
            sl::float3 p4 = {pOri[0]-pDim[0]/2,pOri[1]+pDim[1]/2,pOri[2]-pDim[2]/2};
            sl::float3 p5 = {pOri[0]-pDim[0]/2,pOri[1]+pDim[1]/2,pOri[2]+pDim[2]/2};
            sl::float3 p6 = {pOri[0]+pDim[0]/2,pOri[1]+pDim[1]/2,pOri[2]+pDim[2]/2};
            sl::float3 p7 = {pOri[0]+pDim[0]/2,pOri[1]+pDim[1]/2,pOri[2]-pDim[2]/2};
            std::vector<sl::uint2> newBounding_box_2d = {
                {250,30},
                {1500,30},
                {1500,500},
                {250,500}};
            newBounding_box.push_back(p0);
            newBounding_box.push_back(p1);
            newBounding_box.push_back(p2);
            newBounding_box.push_back(p3);
            newBounding_box.push_back(p4);
            newBounding_box.push_back(p5);
            newBounding_box.push_back(p6);
            newBounding_box.push_back(p7);
            sl::float3 newDimensions = {1.0,1.0,1.0};

            newObject.id = id;
            newObject.position = pOri;
            newObject.velocity = newVelocity;
            newObject.bounding_box_2d = newBounding_box_2d;
            newObject.bounding_box = newBounding_box;
            newObject.dimensions = pDim;
            objects.object_list.push_back(newObject);
            // --> End of the 3D-Bounding box insert

/*          image_ocv.forEach<Pixel>
                (
                    [&](Pixel &pixel, const int * position) -> void {
                        if (pixel.z > 1.5 * pixel.y && pixel.y > pixel.x && pixel.y > 128) {
                            pixel.z = 255; pixel.y = 255; pixel.x = 255;
                        } else {
                            pixel.z = 0; pixel.y = 0; pixel.x = 0;
                        }
                    }
                );*/
            //Update GL View
            viewer.updateView(image_zed, objects);
        }
    }
cv::Mat slMat2cvMat(Mat& input) {
    // Mapping between MAT_TYPE and CV_TYPE
    int cv_type = -1;
    switch (input.getDataType()) {
        case MAT_TYPE::F32_C1: cv_type = CV_32FC1; break;
        case MAT_TYPE::F32_C2: cv_type = CV_32FC2; break;
        case MAT_TYPE::F32_C3: cv_type = CV_32FC3; break;
        case MAT_TYPE::F32_C4: cv_type = CV_32FC4; break;
        case MAT_TYPE::U8_C1: cv_type = CV_8UC1; break;
        case MAT_TYPE::U8_C2: cv_type = CV_8UC2; break;
        case MAT_TYPE::U8_C3: cv_type = CV_8UC3; break;
        case MAT_TYPE::U8_C4: cv_type = CV_8UC4; break;
        default: break;
    }

    // Since cv::Mat data requires a uchar* pointer, we get the uchar1 pointer from sl::Mat (getPtr<T>())
    // cv::Mat and sl::Mat will share a single memory structure
    return cv::Mat(input.getHeight(), input.getWidth(), cv_type, input.getPtr<sl::uchar1>(MEM::GPU));
}

代码按原样工作,但添加ForEach-Loop会导致分段错误。

我问了一个后续问题,这可能是这个问题的答案。

标签: c++opencvgpunvidia-jetson

解决方案


推荐阅读