目标检测之 Selective Search
一. 候选区(Region Proposal)
在使用 R-CNN 等进行目标检测时, 是以候选区的图像作为输入, 候选区包含目标可能性比较大, 因为此区域的颜色纹理等特征比较接近. 相比较于滑动窗口, 候选区更科学, 计算量更小
二. Selective Search 生成候选区
Selective Search 网上有很多介绍, 说了其原理和算法等, 这些都不是本文的重点, 本文的重点是如何用代码去实现. 一共分两种语言, 一种是 Python, 另一种是 C++. 但是都是基于 OpenCV. 所以直接上码, 下面的代码基本上用的都是默认参数, 具体可以参考 OpenCV 官方文档
三. Python 版本
Python 版本用 Jupyter Notebook 来演示
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import cv2 as cv
import matplotlib.pyplot as plt
cur_dir = sys.path[0]
print(cur_dir)
print ("Opencv Version:", cv.__version__) # 我用的 OpenCV 版本是 4.2.0
# 显示读入图像
img = cv.imread(os.path.join(cur_dir, "Cat_Dog.bmp"))
# 因为 OpenCV和 matplotlit 颜色通道相反, 所以需要交换通道后才能显示正常
plt.figure("img_show", figsize = (4, 2))
img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.title("Cat_Dog")
plt.imshow(img_rgb)
显示图像如下
# 创建 SelectiveSearch 对象
ss = cv.ximgproc.segmentation.createSelectiveSearchSegmentation()
# 设置输入图像
ss.setBaseImage(img)
# 单策略模式, 也可以自已选择策略 用 addStrategy 添加
# ss.switchToSingleStrategy()
# 快速模式
# ss.switchToSelectiveSearchFast()
# 质量好, 速度慢
ss.switchToSelectiveSearchQuality()
# 开始处理
rects = ss.process()
print("候选区数量:", len(rects))
运行到上面一段代码的时候, 会报如下的错误, 说没有 ximgproc
这个坑要怎么填? 也简单, 只需要安装 opencv-contrib-pytohon 就好, 但是在安装的时候会有如下图的错误
这个要怎么弄呢? 最后一行红字就提示了解决方法, 要在安装的时候加 --user 选项. 那再用 pip install --user opencv-contrib-python 安装试一下, 果然成功了
如果安装完成后还是报 has no attribute ‘ximgproc’ 的话, 重启一下 Jupyter Notebook 就可以了, 运行结果如下, 说找到了 2213 个候选区
接下来显示找出来的候选框, 只显示了前 32 个
# 显示前 32 个候选框
img_show = img.copy()
for i, rect in enumerate(rects):
# draw rectangle for region proposal till numShowRects
if i < 32:
x, y, w, h = rect
cv.rectangle(img_show, (x, y), (x + w, y + h), (0, 255, 0), 1, cv.LINE_AA)
plt.figure("img_show", figsize = (6, 4))
img_rgb = cv.cvtColor(img_show, cv.COLOR_BGR2RGB)
plt.title("Cat_Dog")
plt.imshow(img_rgb)
plt.show()
Show 一下
你可以修改代码显示其他候选框出来, 全部显示的话, 一片绿, 你自己试一下吧
用快速模式试一下, 快是快了很多, 最后的候选框也少了很多, 全部显示如下
四. C++ 版本
我用的 OpenCV 是 4.3.0, VS2015, 新版本的 OpenCV 如果要使用带 x 前缀的模块的话, 需要编译源码, 直接下载的 exe 文件解压后是没有这些模块的. 也可以下载我编译好的 OpenCV_430 lib 和 dll 文件
准备工作好了之后就可以上码了, 摘自 opencv_contrib-4.3.0\modules\ximgproc\samples\selectivesearchsegmentation_demo.cpp
#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <opencv2/features2d.hpp>
// 这里的 segmentation.hpp 在单独的文件夹中, 所以用的绝对路径, 根据个人情况修改
// lib 和 dll 文件我用源码生成的文件替换了 exe 解压后的文件, 所以就和正常的一样用就好了
#include <D:\\opencv_contrib-4.3.0\\modules\\ximgproc\\include\\opencv2\\ximgproc\\segmentation.hpp>
using namespace cv;
using namespace cv::ximgproc::segmentation;
int main()
{
Ptr<SelectiveSearchSegmentation> ss = createSelectiveSearchSegmentation();
Mat img = imread("E:\\Jupyter_Files\\Selective_Search\\Cat_Dog.bmp", IMREAD_UNCHANGED);
imshow("Input", img);
ss->setBaseImage(img);
// ss->switchToSingleStrategy();
ss->switchToSelectiveSearchFast();
// ss->switchToSelectiveSearchQuality();
std::vector<Rect> vRects;
ss->process(vRects);
Mat img_show = img.clone();
const int nRts = (int)vRects.size();
for (int i = 0; i < nRts; i++)
{
rectangle(img_show, vRects[i], CV_RGB(0, 255, 0));
}
imshow("Output", img_show);
waitKey(0);
return 0;
}
显示结果如下, 和 Python 版本是一样的