当前位置: 首页 > 知识库问答 >
问题:

OpenCV VLFeat Slic函数调用

羊舌子瑜
2023-03-14

我试图使用存储在OpenCV MAT中的输入图像来使用VLFeat库的vl_slic_segment函数。我的代码正在编译和运行,但是输出的超像素值没有意义。以下是我到目前为止的代码:

Mat bgrUChar = imread("/pathtowherever/image.jpg");

Mat bgrFloat;
bgrUChar.convertTo(bgrFloat, CV_32FC3, 1.0/255);
cv::Mat labFloat;
cvtColor(bgrFloat, labFloat, CV_BGR2Lab);

Mat labels(labFloat.size(), CV_32SC1);
vl_slic_segment(labels.ptr<vl_uint32>(),labFloat.ptr<const float>(),labFloat.cols,labFloat.rows,labFloat.channels(),30,0.1,25);

我试着不将它转换为实验室颜色空间,并设置不同的RegionSize/正则化,但输出总是很小。我能够正确的检索标签值,事情是每个标签通常分散在一个小的不连续的区域。

我认为问题是输入数据的格式错误,但我不知道如何将其正确地发送到vl_slic_segment函数。

提前谢谢!

编辑

谢谢您,David,正如您帮助我理解的那样,vl_slic_segment希望将数据排序为[LLLLAAAAAABBBBBB],而OpenCV正在为实验室颜色空间排序数据[LABLABLABLABLAB]。

共有1个答案

皇甫展
2023-03-14

在我的学士学位论文的过程中,我也必须使用VLFEAT的SLIC实现。您可以在GitHub上的lenna.png上找到一个应用VLFEAT的SLIC的简短示例:https://github.com/davidstutz/vlfeat-slic-example。

也许,查看一下main.cpp会帮助您弄清楚如何将OpenCV获得的图像转换为正确的格式:

// OpenCV can be used to read images.
#include <opencv2/opencv.hpp>

// The VLFeat header files need to be declared external.
extern "C" {
    #include "vl/generic.h"
    #include "vl/slic.h"
}

int main() {
    // Read the Lenna image. The matrix 'mat' will have 3 8 bit channels
    // corresponding to BGR color space.
    cv::Mat mat = cv::imread("Lenna.png", CV_LOAD_IMAGE_COLOR);

    // Convert image to one-dimensional array.
    float* image = new float[mat.rows*mat.cols*mat.channels()];
    for (int i = 0; i < mat.rows; ++i) {
        for (int j = 0; j < mat.cols; ++j) {
            // Assuming three channels ...
            image[j + mat.cols*i + mat.cols*mat.rows*0] = mat.at<cv::Vec3b>(i, j)[0];
            image[j + mat.cols*i + mat.cols*mat.rows*1] = mat.at<cv::Vec3b>(i, j)[1];
            image[j + mat.cols*i + mat.cols*mat.rows*2] = mat.at<cv::Vec3b>(i, j)[2];
        }
    }

    // The algorithm will store the final segmentation in a one-dimensional array.
    vl_uint32* segmentation = new vl_uint32[mat.rows*mat.cols];
    vl_size height = mat.rows;
    vl_size width = mat.cols;
    vl_size channels = mat.channels();

    // The region size defines the number of superpixels obtained.
    // Regularization describes a trade-off between the color term and the
    // spatial term.
    vl_size region = 30;        
    float regularization = 1000.;
    vl_size minRegion = 10;

    vl_slic_segment(segmentation, image, width, height, channels, region, regularization, minRegion);

    // Convert segmentation.
    int** labels = new int*[mat.rows];
    for (int i = 0; i < mat.rows; ++i) {
        labels[i] = new int[mat.cols];

        for (int j = 0; j < mat.cols; ++j) {
            labels[i][j] = (int) segmentation[j + mat.cols*i];
        }
    }

    // Compute a contour image: this actually colors every border pixel
    // red such that we get relatively thick contours.
    int label = 0;
    int labelTop = -1;
    int labelBottom = -1;
    int labelLeft = -1;
    int labelRight = -1;

    for (int i = 0; i < mat.rows; i++) {
        for (int j = 0; j < mat.cols; j++) {

            label = labels[i][j];

            labelTop = label;
            if (i > 0) {
                labelTop = labels[i - 1][j];
            }

            labelBottom = label;
            if (i < mat.rows - 1) {
                labelBottom = labels[i + 1][j];
            }

            labelLeft = label;
            if (j > 0) {
                labelLeft = labels[i][j - 1];
            }

            labelRight = label;
            if (j < mat.cols - 1) {
                labelRight = labels[i][j + 1];
            }

            if (label != labelTop || label != labelBottom || label!= labelLeft || label != labelRight) {
                mat.at<cv::Vec3b>(i, j)[0] = 0;
                mat.at<cv::Vec3b>(i, j)[1] = 0;
                mat.at<cv::Vec3b>(i, j)[2] = 255;
            }
        }
    }

    // Save the contour image.
    cv::imwrite("Lenna_contours.png", mat);

    return 0;
}

此外,请查看GitHub存储库中的readme.md。下图显示了将正则化设置为1(100,1000)和将区域大小设置为30(20,40)的一些示例输出。

图1:区域大小设置为30、正则化设置为1的超像素分割。

图2:区域大小设置为30、正则化设置为100的超像素分割。

图3:区域大小设置为30、正则化设置为1000的超像素分割。

图4:区域大小设置为20、正则化设置为1000的超像素分割。

图5:区域大小设置为20、正则化设置为1000的超像素分割。

 类似资料:
  • Python内置了很多有用的函数,我们可以直接调用。 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。可以直接从Python的官方网站查看文档: http://docs.python.org/2/library/functions.html 也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。 调用abs函数: >>> abs(100) 100 >

  • Python内置了很多有用的函数,我们可以直接调用。 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs,只有一个参数。可以直接从Python的官方网站查看文档: http://docs.python.org/3/library/functions.html 也可以在交互式命令行通过help(abs)查看abs函数的帮助信息。 调用abs函数: >>> abs(100) 100 >

  • 函数是C语言编程的核心,通过CGO技术我们不仅仅可以在Go语言中调用C语言函数,也可以将Go语言函数导出为C语言函数。 2.4.1 Go调用C函数 对于一个启用CGO特性的程序,CGO会构造一个虚拟的C包。通过这个虚拟的C包可以调用C语言函数。 /* static int add(int a, int b) { return a+b; } */ import "C" func main(

  • 本文向大家介绍调用Lua函数,包括了调用Lua函数的使用技巧和注意事项,需要的朋友参考一下 示例 在上面的示例中,我们正在执行以下操作: 如第一个示例所示,创建和设置Lua VM 从全局Lua表获取并将Lua函数推入虚拟堆栈 将字符串"Hello C API"作为输入参数推入虚拟堆栈 指示VM使用已在堆栈中的一个参数调用函数 关闭并清理 注意: 简而言之,这会lua_call()从堆栈中弹出函数及

  • 1. 函数调用 我们用下面的代码来研究函数调用的过程。 例 19.1. 研究函数的调用过程 int bar(int c, int d) { int e = c + d; return e; } int foo(int a, int b) { return bar(a, b); } int main(void) { foo(2, 3); return 0; } 如果在编译时加上-g选项

  • 问题内容: 为什么下面的代码不打印任何内容: 我正在Python 3中执行上述代码。我想我缺少了一些非常基本的东西,但无法弄清楚。 问题答案: 返回iterator,直到您要求它之前,它不会处理元素。 将其变成列表以强制处理所有元素: 或将其长度设置为0以不产生列表(如果不需要地图输出): 但是请注意,对于任何以后的代码维护者而言,简单地使用循环都更具可读性:

  • BaaS.invokeFunction(functionName, params, sync) 参数说明 参数 类型 必填 描述 functionName Number 是 云函数名 params Object 否 传递给云函数的参数 sync Bool 否 是否等待返回函数执行结果,默认为 true 返回参数说明 参数 类型 描述 code Number code 为 0 时表示成功执行云函数,

  • 回调函数 返回上级 DDEnumCallback DDEnumCallbackEx EnumModesCallback EnumSurfacesCallback EnumVideoCallback DDEnumCallback 返回目录 DDEnumCallback是用于DirectDrawEnumerate函数的应用程序定义的回调函数。 BOOL WINAPI DDEnumCallback( G