OpenCV中的熵过滤器类似于matlab

时间:2015-11-27 18:06:33

标签: c++ opencv image-segmentation entropy

我正在opencv 3中寻找entropyfilt()函数,所以我很高兴找到这篇文章:Finding entropy in opencv

我正在尝试Umka的优化代码,但我得到的唯一结果是完全白色的图像。 我在代码中唯一改变的是sub_to_ind函数中的数据类型,编译器无法识别int32_t,并且使用int vallues调用该函数,所以我认为这不是问题。

原:

  

static int32_t sub_to_ind(int32_t * coords,int32_t * cumprod,int32_t num_dims)

改变:

  

static int sub_to_ind(int * coords,int * cumprod,int num_dims)

这是我的完整代码:

#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <time.h>


static int sub_to_ind(int *coords, int *cumprod, int num_dims)
{
    int index = 0;
    int k;

    assert(coords != NULL);
    assert(cumprod != NULL);
    assert(num_dims > 0);

    for (k = 0; k < num_dims; k++)
    {
        index += coords[k] * cumprod[k];
    }

    return index;
}

static void ind_to_sub(int p, int num_dims, const int size[],
    int *cumprod, int *coords)
{
    int j;

    assert(num_dims > 0);
    assert(coords != NULL);
    assert(cumprod != NULL);

    for (j = num_dims - 1; j >= 0; j--)
    {
        coords[j] = p / cumprod[j];
        p = p % cumprod[j];
    }
}

void getLocalEntropyImage(cv::Mat &gray, cv::Rect &roi, cv::Mat &entropy)
{
    using namespace cv;
    clock_t func_begin, func_end;
    func_begin = clock();
    //1.define nerghbood model,here it's 9*9
    int neighbood_dim = 2;
    int neighbood_size[] = {9, 9};

    //2.Pad gray_src
    Mat gray_src_mat(gray);
    Mat pad_mat;
    int left = (neighbood_size[0] - 1) / 2;
    int right = left;
    int top = (neighbood_size[1] - 1) / 2;
    int bottom = top;
    copyMakeBorder(gray_src_mat, pad_mat, top, bottom, left, right, BORDER_REPLICATE, 0);
    Mat *pad_src = &pad_mat;
    roi = cv::Rect(roi.x + top, roi.y + left, roi.width, roi.height);

    //3.initial neighbood object,reference to Matlab build-in neighbood object system
    //        int element_num = roi_rect.area();
    //here,implement a histogram by ourself ,each bin calcalate gray value frequence
    int hist_count[256] = {0};
    int neighbood_num = 1;
    for (int i = 0; i < neighbood_dim; i++)
        neighbood_num *= neighbood_size[i];

    //neighbood_corrds_array is a neighbors_num-by-neighbood_dim array containing relative offsets
    int *neighbood_corrds_array = (int *)malloc(sizeof(int)*neighbood_num * neighbood_dim);
    //Contains the cumulative product of the image_size array;used in the sub_to_ind and ind_to_sub calculations.
    int *cumprod = (int *)malloc(neighbood_dim * sizeof(*cumprod));
    cumprod[0] = 1;
    for (int i = 1; i < neighbood_dim; i++)
        cumprod[i] = cumprod[i - 1] * neighbood_size[i - 1];
    int *image_cumprod = (int*)malloc(2 * sizeof(*image_cumprod));
    image_cumprod[0] = 1;
    image_cumprod[1] = pad_src->cols;
    //initialize neighbood_corrds_array
    int p;
    int q;
    int *coords;
    for (p = 0; p < neighbood_num; p++){
        coords = neighbood_corrds_array + p * neighbood_dim;
        ind_to_sub(p, neighbood_dim, neighbood_size, cumprod, coords);
        for (q = 0; q < neighbood_dim; q++)
            coords[q] -= (neighbood_size[q] - 1) / 2;
    }
    //initlalize neighbood_offset in use of neighbood_corrds_array
    int *neighbood_offset = (int *)malloc(sizeof(int) * neighbood_num);
    int *elem;
    for (int i = 0; i < neighbood_num; i++){
        elem = neighbood_corrds_array + i * neighbood_dim;
        neighbood_offset[i] = sub_to_ind(elem, image_cumprod, 2);
    }

    //4.calculate entropy for pixel
    uchar *array = (uchar *)pad_src->data;
    //here,use entroy_table to avoid frequency log function which cost losts of time
    float entroy_table[82];
    const float log2 = log(2.0f);
    entroy_table[0] = 0.0;
    float frequency = 0;
    for (int i = 1; i < 82; i++){
        frequency = (float)i / 81;
        entroy_table[i] = frequency * (log(frequency) / log2);
    }
    int neighbood_index;
    //        int max_index=pad_src->cols*pad_src->rows;
    float e;
    int current_index = 0;
    int current_index_in_origin = 0;
    for (int y = roi.y; y < roi.height; y++){
        current_index = y * pad_src->cols;
        current_index_in_origin = (y - 4) * gray.cols;
        for (int x = roi.x; x < roi.width; x++, current_index++, current_index_in_origin++) {
            for (int j = 0; j<neighbood_num; j++) {
                neighbood_index = current_index + neighbood_offset[j];
                hist_count[array[neighbood_index]]++;
            }
            //get entropy
            e = 0;
            for (int k = 0; k < 256; k++){
                if (hist_count[k] != 0){
                    //                                        int frequency=hist_count[k];
                    e -= entroy_table[hist_count[k]];
                    hist_count[k] = 0;
                }
            }
            ((float *)entropy.data)[current_index_in_origin] = e;
        }
    }
    free(neighbood_offset);
    free(image_cumprod);
    free(cumprod);
    free(neighbood_corrds_array);

    func_end = clock();
    double func_time = (double)(func_end - func_begin) / CLOCKS_PER_SEC;
    std::cout << "func time" << func_time << std::endl;
}

int main(int argc, char** argv)
{
    cv::Mat src; 

    /// Load image
    src = cv::imread(argv[1], 1);
    if (!src.data)
    {
        std::cout << "Usage: EntropyFilter <path_to_image>" << std::endl;
        return -1;
    }
    /// Convert to grayscale
    cvtColor(src, src, cv::COLOR_BGR2GRAY);

    //Calculate Entropy Filter
    cv::Rect roi(0, 0, src.cols, src.rows);
    cv::Mat dst(src.rows, src.cols, CV_32F);
    getLocalEntropyImage(src, roi, dst);
    cv::normalize(dst, dst, 0, 255, cv::NORM_MINMAX);
    cv::Mat entropy;
    dst.convertTo(entropy, CV_8U);

    /// Display results
    cv::namedWindow("Original", cv::WINDOW_AUTOSIZE);
    cv::namedWindow("Entropy Filter", cv::WINDOW_AUTOSIZE);
    cv::namedWindow("Entropy Filter2", cv::WINDOW_AUTOSIZE);

    cv::imshow("Original", src);
    cv::imshow("Entropy Filter", dst);
    cv::imshow("Entropy Filter2", entropy);

    /// Wait until user exits the program
    cv::waitKey(0);

    return 0;
}

我做错了什么或者我应该为我使用的每张图片调整任何参数? (PS:作为比较示例,我在这篇文章中使用了带有字段的图像:https://dsp.stackexchange.com/questions/15221/entropy-frequency-of-a-natural-image

由于

2 个答案:

答案 0 :(得分:1)

我是Opencv和C ++的新手,遇到了同样的问题。 事实证明,你不必对输出图像进行标准化,也不要将其转换为隐蔽。因此,您可以简单地执行此操作

...
getLocalEntropyImage(src, roi, dst);
//dst is your entropy image

/// Display results
cv::namedWindow("Original", cv::WINDOW_AUTOSIZE);
cv::namedWindow("Entropy Filter", cv::WINDOW_AUTOSIZE);

cv::imshow("Original", src);
cv::imshow("Entropy Filter", dst);

/// Wait until user exits the program
cv::waitKey(0);

return 0;

答案 1 :(得分:1)

LMS。

感谢您的出色作品。

我有您代码的Mage Openframeworks版本。 https://github.com/bemoregt/gromitLocalEntropyFilter.git

我提到了该线程的链接。

可以吗?

最好, @bemoregt。