1. Code
nms.cpp
#include <iostream>
#include <vector>
#include <algorithm>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
double IOU(const Rect& r1, const Rect& r2)
{
int x1 = std::max(r1.x, r2.x);
int y1 = std::max(r1.y, r2.y);
int x2 = std::min(r1.x+r1.width, r2.x+r2.width);
int y2 = std::min(r1.y+r1.height, r2.y+r2.height);
int w = std::max(0, (x2-x1+1));
int h = std::max(0, (y2-y1+1));
double inter = w * h;
double o = inter / (r1.area() + r2.area() - inter);
return (o >= 0) ? o : 0;
}
void nms(vector<Rect>& proposals, const double nms_threshold)
{
vector<int> scores;
for(auto i : proposals) scores.push_back(i.area());
vector<int> index;
for(int i = 0; i < scores.size(); ++i){
index.push_back(i);
}
sort(index.begin(), index.end(), [&](int a, int b){
return scores[a] > scores[b];
});
vector<bool> del(scores.size(), false);
for(size_t i = 0; i < index.size(); i++){
if( !del[index[i]]){
for(size_t j = i+1; j < index.size(); j++){
if(IOU(proposals[index[i]], proposals[index[j]]) > nms_threshold){
del[index[j]] = true;
}
}
}
}
vector<Rect> new_proposals;
for(const auto i : index){
if(!del[i]) new_proposals.push_back(proposals[i]);
}
proposals = new_proposals;
}
void test_nms()
{
Mat img = imread("D:\\test\\test.jpg");
Mat img2 = img.clone();
// prepare data
vector<Rect> proposals;
Point2i origin(20, 20);
int w = 100;
int h = 200;
for (auto i : {0,1,2,3,4,5}) proposals.push_back(Rect(origin.x + 10*i, origin.y + 20*i, w - 5*i, h-7*i));
origin.x = 200;
origin.y = 400;
w = 300;
h = 120;
for (auto i : {0,1,2,3,4,5}) proposals.push_back(Rect(origin.x + 10*i, origin.y + 20*i, w - 5*i, h-7*i));
proposals.push_back(Rect(400, 200, 386, 239));
proposals.push_back(Rect(200, 120, 186, 209));
proposals.push_back(Rect(310, 376, 286, 139));
for(auto rect : proposals) rectangle(img, rect, Scalar(0, 255, 255), 2);
imshow("before", img);
// nms
nms(proposals, 0.1);
for(auto rect : proposals) rectangle(img2, rect, Scalar(0, 255, 255), 2);
imshow("after", img2);
waitKey(0);
}
int main()
{
test_nms();
return 0;
}
test.pro
TEMPLATE = app
TARGET = test
CONFIG += console c++11
CONFIG -= qt
CONFIG -= app_bundle
INCLUDEPATH += .
# Input
SOURCES += nms.cpp
win32{
LIBS_PATH = E:\debug\caffe_environment_x86_x64
ARCH = x86 #x64
# opencv
PATH_OPENCV_INCLUDE = $${LIBS_PATH}\OpenCV\opencv310\build\include
PATH_OPENCV_LIBRARIES = $${LIBS_PATH}\OpenCV\opencv310\build\\$${ARCH}\vc12\lib
VERSION_OPENCV = 310
INCLUDEPATH += $${PATH_OPENCV_INCLUDE}
CONFIG(debug, debug|release){
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_core$${VERSION_OPENCV}d
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_highgui$${VERSION_OPENCV}d
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_imgcodecs$${VERSION_OPENCV}d
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_imgproc$${VERSION_OPENCV}d
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_video$${VERSION_OPENCV}d
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_videoio$${VERSION_OPENCV}d
}
CONFIG(release, debug|release){
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_core$${VERSION_OPENCV}
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_highgui$${VERSION_OPENCV}
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_imgcodecs$${VERSION_OPENCV}
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_imgproc$${VERSION_OPENCV}
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_video$${VERSION_OPENCV}
LIBS += -L$${PATH_OPENCV_LIBRARIES} -lopencv_videoio$${VERSION_OPENCV}
}
}
2. Test
qmake && nmake && cd release && test.exe