物体识别的方法很多,可以自己训练model,如基于深度学习的CNN,基于机器学习的svm,通常来讲都是基于DL,这样不会丢失图像的结构信息。
对于物体检测,我们这种情况会采用滑动窗口 的方法,遍历不同尺度下的整副图像,看那个图像块是目标图像。
这种方法是最常见的,但是它存在缺陷
所以计算量是非常的大
这种方法看起来像因果导致,其实不然,这种算法称为“Region Proposal Algorithms",区域规划算法通过分割来识别图像中的潜在目标。对于分割,我们通过领域相似性准则来调整区域,如颜色、纹理等。不像滑动窗口方法,要搜索所有图像的像素位置和不同尺度情况下,因此区域规划算法产生的图像块数量要远远少于滑动窗口算法的,也就是要分类的图像块远远减少。同时,滑动窗口是固定长宽比,而区域规划算法产生的图像块(ROI区域)是不同尺度和不同长宽比的。
区域规划算法有一个很重要的特性是有很高的recall,什么意思尼?就是说产生的图像块包含真正的目标(recall,目标被检测出来的概率)
区域规划算法有以下方法:
1、Objectness
code下载链接:http://groups.inf.ed.ac.uk/calvin/objectness/
2、Constrained Parametric Min-Cuts for Automatic Object Segmentation
code下载链接:http://www.maths.lth.se/matematiklth/personal/sminchis/code/cpmc/index.html
3、Category Independent Object Proposals
code下载链接:http://vision.cs.uiuc.edu/proposals/
4、Randomized Prim
5、Selective Search
以上方法中,selective search 是最常用的,因为它快和很高的recall,于是下面着重讲5方法
选择性搜索是区域规划算法的方法,被用于目标检测。它具有fast 和 high recall 的特性。算法原理:基于颜色、纹理、大小和形状等,将image分层划分为诸多相似区域。
论文参考链接:https://www.koen.me/research/selectivesearch/
1)颜色相似
每个区域计算每个通道25-bin个直方图,即是253=75维的特征描述子
2)纹理相似
每个区域每个通道计算8个方向高斯导数,取10bins 直方图×83=240维的特征描述子
3)大小相似度
4)形状兼容性
最后将以上特征连接起来,a表示的是是否相似,取值为0或1
选择性搜索代码如下:
# coding=utf-8
import cv2
import sys
from cmath import rect
if __name__=="__main__":
# if len(sys.argv)<3:
# print(__doc__)
# sys.exit(1)
#线程加速
cv2.setUseOptimized(True)
cv2.setNumThreads(3)
im=cv2.imread(r"person.jpg")
w,h=int(im.shape[1]*200/im.shape[0]),200
im=cv2.resize(im,(w,h))
ss=cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
ss.setBaseImage(im)
# if sys.argv[2]=="f":
# ss.switchToSelectiveSearchFast()
# elif sys.argv[2]=="q":
# ss.switchToSelectiveSearchQuality()
# else:
# print(__doc__)
# sys.exit(1)
ss.switchToSelectiveSearchFast()
rects=ss.process()
print("区域总数{}".format(len(rects)))
n=40
cv2.createLineSegmentDetector()
while 1:
imout=im.copy()
for i,rect in enumerate(rects):
if i<n:
x,y,w,h=rect
cv2.rectangle(imout,(x,y),(x+w,y+h),(255,0,0),1)
else:
break
cv2.namedWindow("result",cv2.WINDOW_NORMAL)
cv2.imshow("result",imout)
k=cv2.waitKey(0)
if k==27:
break
cv2.destroyAllWindows()
#include
#include
#include
#include
#include
#include
using namespace std;
//using namespace cv;
using namespace cv::ximgproc::segmentation;
int main(int argc,char** argv)
{
// cout << "Hello World!" << endl;
clock_t t1=clock();
if(argc<3){
throw runtime_error("参数个数少于3");
}
setUseOptimized(true);
setNumThreads(4);
Mat img=imread(argv[1]);
int hight=500;
// int width=img.cols*hight/img.rows;
int width=500;
resize(img,img,Size(width,hight));
Mat imgout=img.clone();
Ptr<SelectiveSearchSegmentation> ss=createSelectiveSearchSegmentation();
ss->setBaseImage(img);
if(argv[2]=="f"){
ss->switchToSelectiveSearchFast();
}
else {
ss->switchToSelectiveSearchQuality();
}
std::vector<Rect>rects;
ss->process(rects);
cout<<"总的roi个数是:"<<rects.size()<<endl;
int validrects=100;//有效的roi
cout<<"roi 区域的大小x,y,w,h"<<endl;
while(1)
{
for(int i=0;i<rects.size();++i)
{
if(i<validrects)
{
rectangle(imgout,rects[i],Scalar(0,255,0),2);
cout<<rects[i].x<<" "<<rects[i].y<<" "<<rects[i].width<<" "<<rects[i].height<<endl;
}
}
imshow("result",imgout);
int k=waitKey(0);
if(k==27){
break;
}
}
destroyAllWindows();
cout<<"运行时间是"<<1000*(clock()-t1)/(double)CLOCKS_PER_SEC<<endl;
return 0;
}
对于上述selective search 方法检测出来的roi,我们再用训练好的model对其进行分类即可,这样我们就避免了滑动窗口generate 数以千计的image patches.