NMS simulation code: from the paper efficient non maximum supply

Efficient non maximum suppression

The non maximum suppression mentioned here is a little different from the non maximum suppression mentioned at ordinary times. NMS refers to the application in the detection algorithm, which filters multiple rectangular boxes and filters out the required rectangular boxes. The NMS mentioned in this paper is mainly from neubeck a, good l v. efficient non maximum supply [C] / / International Conference on pattern recognition. IEEE Computer Society, 2006:850-855. If there is a problem with code simulation, please forgive me!

1D NMS for 3-neighbor

#include <vector>
#include <algorithm>
#include <time.h>
#include "opencv2/opencv.hpp"

/** @brief Data non maximum suppression algorithm for 3-Domain situation and index of its maximum value

@param data int Type data, which can be modified appropriately in the code
@param index Index of local maximum obtained
*/
static void nms(const std::vector<int>& data, std::vector<int>& index)
{
    index.clear();

    // Processing data that cannot be processed by the algorithm
    if (data.size() == 1) index.push_back(0);
    else if (data.size() == 2)
    {
        int idx = data[1] > data[0] ? 1 : 0;
        index.push_back(idx);
        return;
    }
    else if (data.size() <= 0) return;
    else {}

    /////////////////////////Data. Size() > = 3 processing//////////////////////////
    int i = 1;
    while (i <= data.size()-2)
    {
        if (data[i] > data[i + 1])
        {
            if (data[i] >= data[i - 1]) index.push_back(i);
        }
        else
        {
            ++i;
            while ((i <= data.size() - 2) && (data[i] <= data[i + 1])) ++i;
            if (i <= data.size() - 2) index.push_back(i);
        }
        i = i + 2;

    } // End Outer while
}


/** @brief Non maximum suppression algorithm for verification writing

@param data Raw data
@param index Maximum index obtained
*/
static bool VerifyNms(std::vector<int>& data, std::vector<int>& index)
{
    for (int i = 0; i < index.size(); ++i)
    {
        int idx = index[i];
        if ((data[idx] >= data[idx - 1]) && (data[idx] > data[idx + 1])) continue;
        return false;
    }

    return true;
}

/** @brief Randomly generate vector type data, the number of data is num

@param data Used to receive the generated data
@param num data Number of data
*/
static void CreateVec(std::vector<int>& data, int num)
{
    data.clear();
    srand(unsigned(time(NULL)));
    for (int i = 0; i < num; ++i)
    {
        data.push_back(i);
    }
    std::random_shuffle(data.begin(), data.end());
}

// Test 3 domain non maximum suppression
void test_Nms3Field()
{
    std::vector<int> data;
    std::vector<int> index;

    const int times = 1000000;
    for (int i = 0; i < times; ++i)
    {
        std::cout << i << ": ";
        CreateVec(data, 8);
        std::cout << "create data !";

        nms(data, index);
        std::cout << "\tIndexNum:" << index.size();

        bool flag = VerifyNms(data, index);
        std::cout << "\tverify:";
        std::cout << ((flag == true) ? " " : "error") << std::endl;
    }

    //cv::waitKey(1);
}

1D NMS for (2n + 1) - neighborhood

#include <vector>
#include <algorithm>
#include <time.h>
#include "opencv2/opencv.hpp"

/** @brief Data non maximum suppression algorithm for 3-Domain situation and index of its maximum value

@param data int Type data, which can be modified appropriately in the code
@param index Index of local maximum obtained
*/
static void nms(const std::vector<int>& data, std::vector<int>& index)
{
    index.clear();

    // Processing data that cannot be processed by the algorithm
    if (data.size() == 1) index.push_back(0);
    else if (data.size() == 2)
    {
        int idx = data[1] > data[0] ? 1 : 0;
        index.push_back(idx);
        return;
    }
    else if (data.size() <= 0) return;
    else {}

    /////////////////////////Data. Size() > = 3 processing//////////////////////////
    int i = 1;
    while (i <= data.size()-2)
    {
        if (data[i] > data[i + 1])
        {
            if (data[i] >= data[i - 1]) index.push_back(i);
        }
        else
        {
            ++i;
            while ((i <= data.size() - 2) && (data[i] <= data[i + 1])) ++i;
            if (i <= data.size() - 2) index.push_back(i);
        }
        i = i + 2;

    } // End Outer while
}


/** @brief Non maximum suppression algorithm for verification writing

@param data Raw data
@param index Maximum index obtained
*/
static bool VerifyNms(std::vector<int>& data, std::vector<int>& index)
{
    for (int i = 0; i < index.size(); ++i)
    {
        int idx = index[i];
        if ((data[idx] >= data[idx - 1]) && (data[idx] > data[idx + 1])) continue;
        return false;
    }

    return true;
}

/** @brief Randomly generate vector type data, the number of data is num

@param data Used to receive the generated data
@param num data Number of data
*/
static void CreateVec(std::vector<int>& data, int num)
{
    data.clear();
    srand(unsigned(time(NULL)));
    for (int i = 0; i < num; ++i)
    {
        data.push_back(i);
    }
    std::random_shuffle(data.begin(), data.end());
}

// Test 3 domain non maximum suppression
void test_Nms3Field()
{
    std::vector<int> data;
    std::vector<int> index;

    const int times = 1000000;
    for (int i = 0; i < times; ++i)
    {
        std::cout << i << ": ";
        CreateVec(data, 8);
        std::cout << "create data !";

        nms(data, index);
        std::cout << "\tIndexNum:" << index.size();

        bool flag = VerifyNms(data, index);
        std::cout << "\tverify:";
        std::cout << ((flag == true) ? "Correct" : "error") << std::endl;
    }

    //cv::waitKey(1);
}

2D (n + 1) × (n + 1) - block NMS

#include <vector>
#include <cassert>
#include "opencv2/opencv.hpp"

/** @brief 2D Non maximum suppression algorithm - mainly for images

@param bin Single channel matrix
@param index Map of the obtained maximum coordinates
@param n Number of fields (2n+1)*(2n+1)
*/
static void nms_2D(cv::Mat& bin, cv::Mat& index, int n)
{
    CV_Assert(bin.type() == CV_8UC1);
    assert((n % 2 == 1) && (n > 0));
    assert((bin.rows >= n) && (bin.cols >= n));

    index = cv::Mat::zeros(bin.rows, bin.cols, CV_8UC1);
    n = n / 2;

    for (int y = n; y <= bin.rows - n - 1; ++y)
    {
        for (int x = n; x <= bin.cols - n - 1; ++x)
        {
            uchar v = bin.at<uchar>(y, x);
            cv::Point m = cv::Point(x, y);

            for (int y2 = y; y2 <= y + n; ++y2)
            {
                for (int x2 = x; x2 <= x + n; ++x2)
                {
                    if ((x2 < 0) || (x2 >= bin.cols) || (y2 < 0) || (y2 >= bin.rows)) continue;
                    if (bin.at<uchar>(y2, x2) > bin.at<uchar>(m.y, m.x))    m = cv::Point(x2, y2);
                } // End x2
            } //End y2

            for (int y2 = m.y - n; y2 <= m.y + n; ++y2)
            {
                for (int x2 = m.x - n; x2 <= m.x + n; ++x2)
                {
                    if ((x2 < 0) || (x2 >= bin.cols) || (y2 < 0) || (y2 >= bin.rows)) continue;
                    if (bin.at<uchar>(y2, x2) > bin.at<uchar>(m.y, m.x))
                    {
                        goto failed;    // goto failed
                    }
                } // End x2
            } // End y2
            index.at<uchar>(m.y, m.x) = 255;
        failed:
            ;
        } // End x
    } // End y
    //cv::waitKey(1);
}


void test_nms_2D()
{

    std::string path = "../Resources/wechat_20180409161327.bmp";
    cv::Mat img = cv::imread(path, cv::IMREAD_GRAYSCALE);
    if (!img.data) return;
    img = ~img;

    cv::Mat index;
    nms_2D(img, index, 5);

    cv::imshow("Original image", img);
    cv::imshow("The results", index);
    cv::waitKey(0);
}

Tags: OpenCV

Posted on Fri, 03 Apr 2020 05:31:12 -0700 by cdinca