OpenCV VLFeat Slic函数调用 [英] OpenCV VLFeat Slic function call

查看:204
本文介绍了OpenCV VLFeat Slic函数调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to use the vl_slic_segment function of the VLFeat library using an input image stored in an OpenCV Mat. My code is compiling and running, but the output superpixel values do not make sense. Here is my code so far :

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);

我尝试过不将其转换为Lab色彩空间并设置不同的regionSize/regularization,但是输出始终非常不整齐.我能够正确检索标签值,但事实是每个标签通常散布在一个不连续的区域上.

I have tried not converting it to the Lab colorspace and setting different regionSize/regularization, but the output is always very glitchy. I am able to retrieve the label values correctly, the thing is the every labels is usually scattered on a little non-contiguous area.

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

I think the problem is the format of my input data is wrong but I can't figure out how to send it properly to the vl_slic_segment function.

提前谢谢!

编辑

谢谢大卫,正如您帮助我理解的那样,vl_slic_segment希望数据按[LLLLLAAAAABBBBB]排序,而OpenCV对其LAB颜色空间订购其数据[LABLABLABLABLAB].

Thank you David, as you helped me understand, vl_slic_segment wants data ordered as [LLLLLAAAAABBBBB] whereas OpenCV is ordering its data [LABLABLABLABLAB] for the LAB color space.

推荐答案

在我的本科论文过程中,我还必须使用VLFeat的SLIC实现.您可以在GitHub的Lenna.png上找到一个应用VLFeat的SLIC的简短示例: https://github. com/davidstutz/vlfeat-slic-example .

In the course of my bachelor thesis I have to use VLFeat's SLIC implementation as well. You can find a short example applying VLFeat's SLIC on Lenna.png on GitHub: https://github.com/davidstutz/vlfeat-slic-example.

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

Maybe, a look at main.cpp will help you figuring out how to convert the images obtained by OpenCV to the right format:

// 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).

In addition, have a look at README.md within the GitHub repository. The following figures show some example outputs of setting the regularization to 1 (100,1000) and setting the region size to 30 (20,40).

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

Figure 1: Superpixel segmentation with region size set to 30 and regularization set to 1.

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

Figure 2: Superpixel segmentation with region size set to 30 and regularization set to 100.

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

Figure 3: Superpixel segmentation with region size set to 30 and regularization set to 1000.

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

Figure 4: Superpixel segmentation with region size set to 20 and regularization set to 1000.

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

Figure 5: Superpixel segmentation with region size set to 20 and regularization set to 1000.

这篇关于OpenCV VLFeat Slic函数调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆