1. 如何使用opencv实现金字塔光流lk跟踪算法
#include <stdio.h>
#include <windows.h>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <opencv2\opencv.hpp>
using namespace cv;
static const double pi = 3.14159265358979323846;
inline static double square(int a)
{
return a * a;
}
/*该函数目的:给img分配内存空间,并设定format,如位深以及channel数*/
inline static void allocateOnDemand(IplImage **img, CvSize size, int depth, int channels)
{
if (*img != NULL) return;
*img = cvCreateImage(size, depth, channels);
if (*img == NULL)
{
fprintf(stderr, "Error: Couldn't allocate image. Out of memory?\n");
exit(-1);
}
}
/*主函数,原程序是读取avi视频文件,然后处理,我简单改成从摄像头直接读取数据*/
int main(int argc, char *argv[])
{
//读取摄像头
VideoCapture cap(0);
//读取视频文件
//VideoCapture cap; cap.open("optical_flow_input.avi");
if (!cap.isOpened())
{
return -1;
}
Mat frame;
/*
bool stop = false;
while (!stop)
{
cap >> frame;
// cvtColor(frame, edges, CV_RGB2GRAY);
// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
// Canny(edges, edges, 0, 30, 3);
// imshow("当前视频", edges);
imshow("当前视频", frame);
if (waitKey(30) >= 0)
stop = true;
}
*/
//CvCapture *input_video = cvCaptureFromFile( "optical_flow_input.avi" );
//cv::VideoCapture cap = *(cv::VideoCapture *) userdata;
//if (input_video == NULL)
// {
// fprintf(stderr, "Error: Can't open video device.\n");
// return -1;
// }
/*先读取一帧,以便得到帧的属性,如长、宽等*/
//cvQueryFrame(input_video);
/*读取帧的属性*/
CvSize frame_size;
frame_size.height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
frame_size.width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
/*********************************************************/
/*用于把结果写到文件中去,非必要
int frameW = frame_size.height; // 744 for firewire cameras
int frameH = frame_size.width; // 480 for firewire cameras
VideoWriter writer("VideoTest.avi", -1, 25.0, cvSize(frameW, frameH), true);
/*开始光流法*/
//VideoWriter writer("VideoTest.avi", CV_FOURCC('D', 'I', 'V', 'X'), 25.0, Size(640, 480), true);
while (true)
{
static IplImage *frame = NULL, *frame1 = NULL, *frame1_1C = NULL,
*frame2_1C = NULL, *eig_image = NULL, *temp_image = NULL,
*pyramid1 = NULL, *pyramid2 = NULL;
Mat framet;
/*获取第一帧*/
// cap >> framet;
cap.read(framet);
Mat edges;
//黑白抽象滤镜模式
// cvtColor(framet, edges, CV_RGB2GRAY);
// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
// Canny(edges, edges, 0, 30, 3);
//转换mat格式到lpiimage格式
frame = &IplImage(framet);
if (frame == NULL)
{
fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n");
return -1;
}
/*由于opencv的光流函数处理的是8位的灰度图,所以需要创建一个同样格式的
IplImage的对象*/
allocateOnDemand(&frame1_1C, frame_size, IPL_DEPTH_8U, 1);
/* 把摄像头图像格式转换成OpenCV惯常处理的图像格式*/
cvConvertImage(frame, frame1_1C, 0);
/* 我们需要把具有全部颜色信息的原帧保存,以备最后在屏幕上显示用*/
allocateOnDemand(&frame1, frame_size, IPL_DEPTH_8U, 3);
cvConvertImage(frame, frame1, 0);
/* 获取第二帧 */
//cap >> framet;
cap.read(framet);
// cvtColor(framet, edges, CV_RGB2GRAY);
// GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
// Canny(edges, edges, 0, 30, 3);
frame = &IplImage(framet);
if (frame == NULL)
{
fprintf(stderr, "Error: Hmm. The end came sooner than we thought.\n");
return -1;
}
/*原理同上*/
allocateOnDemand(&frame2_1C, frame_size, IPL_DEPTH_8U, 1);
cvConvertImage(frame, frame2_1C, 0);
/*********************************************************
开始shi-Tomasi算法,该算法主要用于feature selection,即一张图中哪些是我
们感兴趣需要跟踪的点(interest point)
input:
* "frame1_1C" 输入图像.
* "eig_image" and "temp_image" 只是给该算法提供可操作的内存区域.
* 第一个".01" 规定了特征值的最小质量,因为该算法要得到好的特征点,哪就
需要一个选择的阈值
* 第二个".01" 规定了像素之间最小的距离,用于减少运算复杂度,当然也一定
程度降低了跟踪精度
* "NULL" 意味着处理整张图片,当然你也可以指定一块区域
output:
* "frame1_features" 将会包含fram1的特征值
* "number_of_features" 将在该函数中自动填充上所找到特征值的真实数目,
该值<= 400
**********************************************************/
/*开始准备该算法需要的输入*/
/* 给eig_image,temp_image分配空间*/
allocateOnDemand(&eig_image, frame_size, IPL_DEPTH_32F, 1);
allocateOnDemand(&temp_image, frame_size, IPL_DEPTH_32F, 1);
/* 定义存放frame1特征值的数组,400只是定义一个上限 */
CvPoint2D32f frame1_features[400];
int number_of_features = 400;
/*开始跑shi-tomasi函数*/
cvGoodFeaturesToTrack(frame1_1C, eig_image, temp_image,
frame1_features, &number_of_features, .01, .01, NULL);
/**********************************************************
开始金字塔Lucas Kanade光流法,该算法主要用于feature tracking,即是算出
光流,并跟踪目标。
input:
* "frame1_1C" 输入图像,即8位灰色的第一帧
* "frame2_1C" 第二帧,我们要在其上找出第一帧我们发现的特征点在第二帧
的什么位置
* "pyramid1" and "pyramid2" 是提供给该算法可操作的内存区域,计算中间
数据
* "frame1_features" 由shi-tomasi算法得到的第一帧的特征点.
* "number_of_features" 第一帧特征点的数目
* "optical_flow_termination_criteria" 该算法中迭代终止的判别,这里是
epsilon<0.3,epsilon是两帧中对应特征窗口的光度之差的平方,这个以后的文
章会讲
* "0" 这个我不知道啥意思,反正改成1就出不来光流了,就用作者原话解释把
means disable enhancements. (For example, the second array isn't
pre-initialized with guesses.)
output:
* "frame2_features" 根据第一帧的特征点,在第二帧上所找到的对应点
* "optical_flow_window" lucas-kanade光流算法的运算窗口,具体lucas-kanade
会在下一篇详述
* "5" 指示最大的金字塔层数,0表示只有一层,那就是没用金字塔算法
* "optical_flow_found_feature" 用于指示在第二帧中是否找到对应特征值,
若找到,其值为非零
* "optical_flow_feature_error" 用于存放光流误差
**********************************************************/
/*开始为pyramid lucas kanade光流算法输入做准备*/
CvPoint2D32f frame2_features[400];
/* 该数组相应位置的值为非零,如果frame1中的特征值在frame2中找到 */
char optical_flow_found_feature[400];
/* 数组第i个元素表对应点光流误差*/
float optical_flow_feature_error[400];
/*lucas-kanade光流法运算窗口,这里取3*3的窗口,可以尝试下5*5,区别就是5*5
出现aperture problem的几率较小,3*3运算量小,对于feature selection即shi-tomasi算法来说足够了*/
CvSize optical_flow_window = cvSize(5, 5);
// CvSize optical_flow_window = cvSize(5, 5);
/* 终止规则,当完成20次迭代或者当epsilon<=0.3,迭代终止,可以尝试下别的值*/
CvTermCriteria optical_flow_termination_criteria= cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3);
/*分配工作区域*/
allocateOnDemand(&pyramid1, frame_size, IPL_DEPTH_8U, 1);
allocateOnDemand(&pyramid2, frame_size, IPL_DEPTH_8U, 1);
/*开始跑该算法*/
cvCalcOpticalFlowPyrLK(frame1_1C, frame2_1C, pyramid1, pyramid2,frame1_features, frame2_features, number_of_features,
optical_flow_window, 5, optical_flow_found_feature,optical_flow_feature_error, optical_flow_termination_criteria, 0);
/*画光流场,画图是依据两帧对应的特征值,
这个特征值就是图像上我们感兴趣的点,如边缘上的点P(x,y)*/
for (int i = 0; i< number_of_features; i++)
{
/* 如果没找到对应特征点 */
if (optical_flow_found_feature[i] == 0)
continue;
int line_thickness;
line_thickness = 1;
/* CV_RGB(red, green, blue) is the red, green, and blue components
* of the color you want, each out of 255.
*/
CvScalar line_color;
line_color = CV_RGB(255, 0, 0);
/*画箭头,因为帧间的运动很小,所以需要缩放,不然看不见箭头,缩放因子为3*/
CvPoint p, q;
p.x = (int)frame1_features[i].x;
p.y = (int)frame1_features[i].y;
q.x = (int)frame2_features[i].x;
q.y = (int)frame2_features[i].y;
double angle;
angle = atan2((double)p.y - q.y, (double)p.x - q.x);
double hypotenuse;
hypotenuse = sqrt(square(p.y - q.y) + square(p.x - q.x));
/*执行缩放*/
q.x = (int)(p.x - 5 * hypotenuse * cos(angle));
q.y = (int)(p.y - 5 * hypotenuse * sin(angle));
/*画箭头主线*/
/* "frame1"要在frame1上作画.
* "p" 线的开始点.
* "q" 线的终止点.
* "CV_AA" 反锯齿.
* "0" 没有小数位.
*/
cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);
/* 画箭的头部*/
p.x = (int)(q.x + 9 * cos(angle + pi / 4));
p.y = (int)(q.y + 9 * sin(angle + pi / 4));
cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);
p.x = (int)(q.x + 9 * cos(angle - pi / 4));
p.y = (int)(q.y + 9 * sin(angle - pi / 4));
cvLine(frame1, p, q, line_color, line_thickness, CV_AA, 0);
}
/*显示图像*/
/*创建一个名为optical flow的窗口,大小自动改变*/
cvNamedWindow("Optical Flow", CV_WINDOW_NORMAL);
cvFlip(frame1, NULL, 2);
cvShowImage("Optical Flow", frame1);
/*延时,要不放不了*/
cvWaitKey(33);
/*写入到文件中去*/
// cv::Mat m = cv::cvarrToMat(frame1);//转换lpimgae到mat格式
// writer << m;//opencv3.0 version writer
}
cap.release();
cvWaitKey(33);
system("pause");
}
2. SIFT特征的原理
SIFT特征不只具有尺度不变性,即使改变图像的旋转角度,亮度或拍摄视角,仍然能够得到好的检测效果。
这是一个初始化操作,尺度空间理论目的是模拟图像数据的多尺度特征。高斯卷积核是实现尺度变换的唯一线性核,于是一副二维图像的尺度空间定义为:
下图所示不同σ下图像尺度空间:
关于尺度空间的理解说明:2kσ中的2是必须的,尺度空间是连续的。在 Lowe的论文中 ,将第0层的初始尺度定为1.6(最模糊),图片的初始尺度定为0.5(最清晰). 在检测极值点前对原始图像的高斯平滑以致图像丢失高频信息,所以 Lowe 建议在建立尺度空间前首先对原始图像长宽扩展一倍,以保留原始图像信息,增加特征点数量。尺度越大图像越模糊。
图像金字塔的建立:对于一幅图像I,建立其在不同尺度(scale)的图像,也成为子八度(octave),这是为了scale-invariant,也就是在任何尺度都能够有对应的特征点,第一个子八度的scale为原图大小,后面每个octave为上一个octave降采样的结果,即原图的1/4(长宽分别减半),构成下一个子八度(高一层金字塔)。
注意:使用Difference of Gaussian图像的极大极小值近似寻找特征点计算简单,是尺度归一化的LoG算子的近似
为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。
一个点如果在DOG尺度空间本层以及上下两层的26个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点,如图所示。
整个高斯金字塔如下图所示,其中每个Octave代表一个金字塔,同一个金字塔内图像尺寸一样,同一个金字塔内每张图通过不同的高斯卷积核产生。
在极值比较的过程中,每一组图像的首末两层是无法进行极值比较的,为了满足尺度变化的连续性,我们在每一组图像的顶层继续用高斯模糊生成了 3 幅图像,高斯金字塔有每组S+3层图像。DOG金字塔每组有S+2层图像。
使用Laplacian of Gaussian能够很好地找到找到图像中的兴趣点,但是需要大量的计算量,所以使用Difference of Gaussian图像的极大极小值近似寻找特征点.DOG算子计算简单,是尺度归一化的LoG算子的近似,有关DOG寻找特征点的介绍及方法详见 http://blog.csdn.net/abcjennifer/article/details/7639488 ,极值点检测用的Non-Maximal Suppression。
这一步本质上要去掉DoG局部曲率非常不对称的像素。(不理解)
通过拟和三维二次函数以精确确定关键点的 位置 和 尺度 (达到亚像素精度),同时去除低对比度的关键点和不稳定的边缘响应点(因为DoG算子会产生较强的边缘响应),以增强匹配稳定性、提高抗噪声能力,在这里使用近似Harris Corner检测器。
计算过程摘录如下:(还没有自行推导)
①空间尺度函数泰勒展开式如下:
的值在两个特征值相等的时候最小,随着r的增大而增大,因此,为了检测主曲率是否在某域值r下,只需检测
if (α+β)/ αβ> (r+1)2
/r, throw it out. 在Lowe的文章中,取r=10。
上一步中确定了每幅图中的特征点,为每个特征点计算一个方向,依照这个方向做进一步的计算, 利用关键点邻域像素的梯度方向分布特性为每个关键点指定方向参数,使算子具备旋转不变性。
梯度直方图的范围是0~360度,其中每10度一个柱,总共36个柱。随着距 中心点越远的领域其对直方图的贡献也响应减小。Lowe论文中还提到要使用高斯函数对直方图进行平滑,减少突变的影响。这主要是因为SIFT算法只考虑了尺度和旋转不变形,没有考虑仿射不变性。通过高斯平滑,可以使关键点附近的梯度幅值有较大权重,从而部分弥补没考虑仿射不变形产生的特征点不稳定。
通常离散的梯度直方图要进行插值拟合处理,以求取更精确的方向角度值。
在实际计算时,我们在以关键点为中心的邻域窗口内采样,并用直方图统计邻域像素的梯度方向。梯度直方图的范围是0~360度,其中每45度一个柱,总共8个柱, 或者每10度一个柱,总共36个柱。Lowe论文中还提到要使用高斯函数对直方图进行平滑,减少突变的影响。直方图的峰值则代表了该关键点处邻域梯度的主方向,即作为该关键点的方向。
直方图中的峰值就是主方向,其他的达到最大值80%的方向可作为辅助方向
Identify peak and assign orientation and sum of magnitude to key point.
** The user may choose a threshold to exclude key points based on their** assigned sum of magnitudes.
直方图峰值代表该关键点处邻域内图像梯度的主方向,也就是该 关键点的主方向 。在梯度方向直方图中,当存在另一个相当于主峰值 80%能量的峰值时,则将这个方向认为是该 关键点的辅方向 。所以一个关键点可能检测得到多个方向,这可以增强匹配的鲁棒性。Lowe的论文指出大概有15%关键点具有多方向,但这些点对匹配的稳定性至为关键。
获得图像关键点主方向后,每个关键点有三个信息(x,y,σ,θ):位置、尺度、方向。由此我们可以确定一个SIFT特征区域。通常使用一个带箭头的圆或直接使用箭头表示SIFT区域的三个值:中心表示特征点位置,半径表示关键点尺度(r=2.5σ),箭头表示主方向。具有多个方向的关键点可以复制成多份,然后将方向值分别赋给复制后的关键点。如下图:
通过对关键点周围图像区域分块,计算块内梯度直方图,生成具有独特性的向量,这个向量是该区域图像信息的一种抽象,具有唯一性。
首先将坐标轴旋转为关键点的方向,以确保旋转不变性。以关键点为中心取8×8的窗口。
Figure.16*16的图中其中1/4的特征点梯度方向及scale,右图为其加权到8个主方向后的效果。
图左部分的中央为当前关键点的位置,每个小格代表关键点邻域所在尺度空间的一个像素,利用公式求得每个像素的梯度幅值与梯度方向,箭头方向代表该像素的梯度方向,箭头长度代表梯度模值,然后用高斯窗口对其进行加权运算。
图中蓝色的圈代表高斯加权的范围(越靠近关键点的像素梯度方向信息贡献越大)。然后在每4×4的小块上计算8个方向的梯度方向直方图,绘制每个梯度方向的累加值,即可形成一个种子点,如图右部分示。此图中一个关键点由2×2共4个种子点组成,每个种子点有8个方向向量信息。这种邻域方向性信息联合的思想增强了算法抗噪声的能力,同时对于含有定位误差的特征匹配也提供了较好的容错性。
计算keypoint周围的16*16的window中每一个像素的梯度,而且使用高斯下降函数降低远离中心的权重。
在每个4 4的1/16象限中,通过加权梯度值加到直方图8个方向区间中的一个,计算出一个梯度方向直方图。
这样就可以对每个feature形成一个4 4 8=128维的描述子,每一维都可以表示4 4个格子中一个的scale/orientation. 将这个向量归一化之后,就进一步去除了光照的影响。
生成了A、B两幅图的描述子,(分别是k1 128维和k2 128维),就将两图中各个scale(所有scale)的描述子进行匹配,匹配上128维即可表示两个特征点match上了。
实际计算过程中,为了增强匹配的稳健性,Lowe建议对每个关键点使用4×4共16个种子点来描述,这样对于一个关键点就可以产生128个数据,即最终形成128维的SIFT特征向量。此时SIFT特征向量已经去除了尺度变化、旋转等几何变形因素的影响,再继续将特征向量的长度归一化,则可以进一步去除光照变化的影响。 当两幅图像的SIFT特征向量生成后,下一步我们采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。取图像1中的某个关键点,并找出其与图像2中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,Lowe提出了比较最近邻距离与次近邻距离的方法,距离比率ratio小于某个阈值的认为是正确匹配。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。Lowe推荐ratio的阈值为0.8。但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0. 4~0. 6之间最佳,小于0. 4的很少有匹配点,大于0. 6的则存在大量错误匹配点。(如果这个地方你要改进,最好给出一个匹配率和ration之间的关系图,这样才有说服力)作者建议ratio的取值原则如下:
ratio=0. 4对于准确度要求高的匹配;ratio=0. 6对于匹配点数目要求比较多的匹配; ratio=0. 5一般情况下。也可按如下原则:当最近邻距离<200时ratio=0. 6,反之ratio=0. 4。ratio的取值策略能排分错误匹配点。
当两幅图像的SIFT特征向量生成后,下一步我们采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。取图像1中的某个关键点,并找出其与图像2中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。
3. 图像集合变换第几
一、改变色彩空间:
1.最常用的颜色转换方法:BGR和GRAY、BGR和HSV
2.对象追踪:给出想要追踪的对象的颜色,就可以提取该对象。需要先将其转换为HSV颜色空间。
二、图像集合变换:
可以实现:
1.缩放(resize)
2.平移、旋转、仿射变换(warpAffine)
3.透视变换(warpPerspective)
三、图像阈值:
1.简单阈值:
用来二分化图像。
2.自适应阈值:
对于有着不同照明条件的图像,用简单阈值明显不太合适,这时可以使用自适应阈值。
3.大津二值化:
在这个方法中可以不给出具体的阈值而是让其自动找到一个合适的阈值。
四、平滑图像
1.平均
通过将图像和盒式滤波器进行卷积来完成的,取内核区域下所有像素的平均值并替换中心元素。我们应该指定内核的宽度和高度。
2.高斯模糊
使用高斯核来替代盒式滤波器,同样指定它的宽度和高度(应为正数和奇数)。还可以指定X和Y方向的标准偏差(?),如果两者都为零则跟根据内核大小自动计算。高斯模糊对于图像去除高斯噪音非常有效。
3.中值模糊
这里,函数cv.medianBlur()取内核区域下所有像素的中值,并将中心元素(?)替换为该中值。这对图像中的椒盐噪声非常有效。有趣的是,在之前的过滤器中,中心元素是新计算的值(可能是原图像中的像素值或新值),但是在中值模糊中,中心元素总是被图像中的某个像素值替换。它有效地降低了噪音。它的内核大小应该是一个正奇数。
4.双边过滤
双边过滤可以解决高斯模糊总会模糊边缘的不足。双边过滤也在空间上采用高斯滤波器,但多了一个用于像素差的函数的高斯滤波器。前者确保只考虑附近的像素进行模糊处理;而后者只考虑那些与中心像素具有相似强度的像素进行模糊处理。因为边缘处的像素会有很大的强度变化,所以它保留了边缘。
五、形态变换
1.侵蚀
内核在图像中滑动,只有当内核区域中的所有像素都为1时,该区域中的一个像素(1或0)才会被认为是1,否则它会被侵蚀(变为0)。即根据内核大小前景物体的边缘会被丢弃(即1变为0,白变黑),具体表现为前景物体的厚度增大或减少,或者是图像中的白色区域变化。
2.扩张
与侵蚀相反,如果内核区域内的至少一个像素为1,则该区域都为1。通常用于侵蚀消除了白噪声后,可以再将其扩张到原来大小,噪音就消失了。
3.opening
先侵蚀再扩张,可用于消除前景物体以外的小白点。
4.closing
先扩张再侵蚀,可用于消除前景物体的小孔或小黑点。
5.形态梯度
生成前景物体的轮廓。
6.top hat
输出原图和opening后的差异。
7.black hat
输出原图和closing后的差异。
8.getStructuringElement
生成圆形、椭圆形或十字形的内核。(长方形可由Numpy创建)
六、Image Gradients(?)
使用Soble、Scharr、Laplacian导数来锐化图像。
七、Canny 边缘检测
这是一个多阶段算法。
1.降噪:由于边缘检测容易受到图像中噪声的影响,因此第一步是使用 5x5 高斯滤波器去除图像中的噪声。
2.寻找图像的强度梯度:然后在水平和垂直方向上使用 Sobel 内核对平滑后的图像进行滤波,以获得水平方向的一阶导数和垂直方向。
3.非最大抑制:在获得梯度幅度和方向后,对图像进行全面扫描以去除可能不构成边缘的任何不需要的像素。为此,在每个像素处,检查像素是否是其邻域中沿梯度方向的局部最大值。
4.迟滞阈值:这个阶段决定哪些所有的边都是真正的边,哪些不是。为此,我们需要两个阈值 minVal 和 maxVal。任何强度梯度大于 maxVal 的边缘肯定是边缘,低于 minVal 的边缘肯定是非边缘,因此丢弃。位于这两个阈值之间的那些根据它们的连通性被分类为边缘或非边缘。如果它们连接到“确定边缘”像素,则它们被认为是边缘的一部分。否则,它们也会被丢弃。
八、图像金字塔(代码?)
在搜索图像中的某些内容时,例如人脸,我们不确定该对象在所述图像中的大小。在这种情况下,我们需要创建一组具有不同分辨率的相同图像并在所有图像中搜索对象。这些具有不同分辨率的图像集称为图像金字塔。
拉普拉斯金字塔是由高斯金字塔形成的。没有专门的功能。拉普拉斯金字塔图像仅类似于边缘图像。它的大部分元素都是零。它们用于图像压缩。拉普拉斯金字塔中的一个级别是由高斯金字塔中的该级别与高斯金字塔中其上层的扩展版本之间的差异形成的。
金字塔的一种应用是图像混合。例如,在图像拼接中,您需要将两张图像堆叠在一起,但由于图像之间的不连续性,它可能看起来不太好。在这种情况下,使用金字塔进行图像混合可为您提供无缝混合,而不会在图像中留下太多数据。
九、模板匹配
模板匹配是一种在较大图像中搜索和查找模板图像位置的方法。为此,OpenCV 附带了一个函数cv.matchTemplate()。它只是将模板图像滑到输入图像上(如在 2D 卷积中),并在模板图像下比较输入图像的模板和补丁。OpenCV 中实现了几种比较方法。它返回一个灰度图像,其中每个像素表示该像素的邻域与模板匹配的程度。
假设您正在搜索一个多次出现的对象,cv.minMaxLoc()不会为您提供所有位置。在这种情况下,我们将使用阈值。
4. ERDAS软件如何进行金字塔算法的融合ENVI、PCI有没有这项功能! 急急急!!!
没明白你的问题 erdas提供很多融合算法 金字塔只是为了加速图像显示
5. [图像算法]-Faster RCNN详解
paper: Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks
Tensorflow-faster r-cnn github: Tensorflow Faster RCNN for Object Detection
faster rcnn是何凯明等大神在2015年提出目标检测算法,该算法在2015年的ILSVRV和COCO竞赛中获得多项第一。该算法在fast rcnn基础上提出了RPN候选框生成算法,使得目标检测速度大大提高。
(1)image input;
(2)利用selective search 算法在图像中从上到下提取2000个左右的Region Proposal;
(3)将每个Region Proposal缩放(warp)成227*227的大小并输入到CNN,将CNN的fc7层的输出作为特征;
(4)将每个Region Proposal提取的CNN特征输入到SVM进行分类;
(5)对于SVM分好类的Region Proposal做边框回归,用Bounding box回归值校正原来的建议窗口,生成预测窗口坐标.
缺陷:
(1) 训练分为多个阶段,步骤繁琐:微调网络+训练SVM+训练边框回归器;
(2) 训练耗时,占用磁盘空间大;5000张图像产生几百G的特征文件;
(3) 速度慢:使用GPU,VGG16模型处理一张图像需要47s;
(4) 测试速度慢:每个候选区域需要运行整个前向CNN计算;
(5) SVM和回归是事后操作,在SVM和回归过程中CNN特征没有被学习更新.
(1)image input;
(2)利用selective search 算法在图像中从上到下提取2000个左右的建议窗口(Region Proposal);
(3)将整张图片输入CNN,进行特征提取;
(4)把建议窗口映射到CNN的最后一层卷积feature map上;
(5)通过RoI pooling层使每个建议窗口生成固定尺寸的feature map;
(6)利用Softmax Loss(探测分类概率) 和Smooth L1 Loss(探测边框回归)对分类概率和边框回归(Bounding box regression)联合训练.
相比R-CNN,主要两处不同:
(1)最后一层卷积层后加了一个ROI pooling layer;
(2)损失函数使用了多任务损失函数(multi-task loss),将边框回归直接加入到CNN网络中训练
改进:
(1) 测试时速度慢:R-CNN把一张图像分解成大量的建议框,每个建议框拉伸形成的图像都会单独通过CNN提取特征.实际上这些建议框之间大量重叠,特征值之间完全可以共享,造成了运算能力的浪费.
FAST-RCNN将整张图像归一化后直接送入CNN,在最后的卷积层输出的feature map上,加入建议框信息,使得在此之前的CNN运算得以共享.
(2) 训练时速度慢:R-CNN在训练时,是在采用SVM分类之前,把通过CNN提取的特征存储在硬盘上.这种方法造成了训练性能低下,因为在硬盘上大量的读写数据会造成训练速度缓慢.
FAST-RCNN在训练时,只需要将一张图像送入网络,每张图像一次性地提取CNN特征和建议区域,训练数据在GPU内存里直接进Loss层,这样候选区域的前几层特征不需要再重复计算且不再需要把大量数据存储在硬盘上.
(3) 训练所需空间大:R-CNN中独立的SVM分类器和回归器需要大量特征作为训练样本,需要大量的硬盘空间.FAST-RCNN把类别判断和位置回归统一用深度网络实现,不再需要额外存储.
(4) 由于ROI pooling的提出,不需要再input进行Corp和wrap操作,避免像素的损失,巧妙解决了尺度缩放的问题.
(1)输入测试图像;
(2)将整张图片输入CNN,进行特征提取;
(3)用RPN先生成一堆Anchor box,对其进行裁剪过滤后通过softmax判断anchors属于前景(foreground)或者后景(background),即是物体or不是物体,所以这是一个二分类;同时,另一分支bounding box regression修正anchor box,形成较精确的proposal(注:这里的较精确是相对于后面全连接层的再一次box regression而言)
(4)把建议窗口映射到CNN的最后一层卷积feature map上;
(5)通过RoI pooling层使每个RoI生成固定尺寸的feature map;
(6)利用Softmax Loss(探测分类概率) 和Smooth L1 Loss(探测边框回归)对分类概率和边框回归(Bounding box regression)联合训练.
相比FASTER-RCNN,主要两处不同:
(1)使用RPN(Region Proposal Network)代替原来的Selective Search方法产生建议窗口;
(2)产生建议窗口的CNN和目标检测的CNN共享
改进:
(1) 如何高效快速产生建议框?
FASTER-RCNN创造性地采用卷积网络自行产生建议框,并且和目标检测网络共享卷积网络,使得建议框数目从原有的约2000个减少为300个,且建议框的质量也有本质的提高.
从上面的三张图可以看出,Faster R CNN由下面几部分组成:
1.数据集,image input
2.卷积层CNN等基础网络,提取特征得到feature map
3-1.RPN层,再在经过卷积层提取到的feature map上用一个3x3的slide window,去遍历整个feature map,在遍历过程中每个window中心按rate,scale(1:2,1:1,2:1)生成9个anchors,然后再利用全连接对每个anchors做二分类(是前景还是背景)和初步bbox regression,最后输出比较精确的300个ROIs。
3-2.把经过卷积层feature map用ROI pooling固定全连接层的输入维度。
4.然后把经过RPN输出的rois映射到ROIpooling的feature map上进行bbox回归和分类。
SPP-Net是出自论文《Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition》
由于一般的网络结构中都伴随全连接层,全连接层的参数就和输入图像大小有关,因为它要把输入的所有像素点连接起来,需要指定输入层神经元个数和输出层神经元个数,所以需要规定输入的feature的大小。而SPP-NET正好解决了这个问题。
如果原图输入是224x224,对于conv5出来后的输出,是13x13x256的,可以理解成有256个这样的filter,每个filter对应一张13x13的activation map.如果像上图那样将activation map pooling成4x4 2x2 1x1三张子图,做max pooling后,出来的特征就是固定长度的(16+4+1)x256那么多的维度了.如果原图的输入不是224x224,出来的特征依然是(16+4+1)x256;直觉地说,可以理解成将原来固定大小为(3x3)窗口的pool5改成了自适应窗口大小,窗口的大小和activation map成比例,保证了经过pooling后出来的feature的长度是一致的.
总结而言,当网络输入的是一张任意大小的图片,这个时候我们可以一直进行卷积、池化,直到网络的倒数几层的时候,也就是我们即将与全连接层连接的时候,就要使用金字塔池化,使得任意大小的特征图都能够转换成固定大小的特征向量,这就是空间金字塔池化的意义(多尺度特征提取出固定大小的特征向量)。
ROI pooling layer实际上是SPP-NET的一个精简版,SPP-NET对每个proposal使用了不同大小的金字塔映射,而ROI pooling layer只需要下采样到一个7x7的特征图.对于VGG16网络conv5_3有512个特征图,这样所有region proposal对应了一个7*7*512维度的特征向量作为全连接层的输入.
为什么要pooling成7×7的尺度?是为了能够共享权重。Faster RCNN除了用到VGG前几层的卷积之外,最后的全连接层也可以继续利用。当所有的RoIs都被pooling成(512\×7\×7)的feature map后,将它reshape 成一个一维的向量,就可以利用VGG16预训练的权重,初始化前两层全连接.
那么经过何种变换才能从图11中的窗口P变为窗口呢?比较简单的思路就是:
注意:只有当Proposal和Ground Truth比较接近时(线性问题),我们才能将其作为训练样本训练我们的线性回归模型,否则会导致训练的回归模型不work(当Proposal跟GT离得较远,就是复杂的非线性问题了,此时用线性回归建模显然不合理).这个也是G-CNN: an Iterative Grid Based Object Detector多次迭代实现目标准确定位的关键. 线性回归就是给定输入的特征向量X,学习一组参数W,使得经过线性回归后的值跟真实值Y(Ground Truth)非常接近.即.那么Bounding-box中我们的输入以及输出分别是什么呢?
如上图中标识:
① rpn_cls:60*40*512-d ⊕ 1*1*512*18 > 60*40*92 逐像素对其9个Anchor box进行二分类
② rpn_bbox:60*40*512-d ⊕ 1*1*512*36>60*40*9*4 逐像素得到其9个Anchor box四个坐标信息
逐像素对Anchors分类标记
① 去除掉超过1000*600这原图的边界的anchor box
② 如果anchor box与ground truth的IoU值最大,标记为正样本,label=1
③ 如果anchor box与ground truth的IoU>0.7,标记为正样本,label=1
④ 如果anchor box与ground truth的IoU<0.3,标记为负样本,label=0
剩下的既不是正样本也不是负样本,不用于最终训练,label=-1
逐像素Bbox回归纠正
除了对anchor box进行标记外,另一件事情就是计算anchor box与ground truth之间的偏移量
令:ground truth:标定的框也对应一个中心点位置坐标x ,y 和宽高w ,h
anchor box: 中心点位置坐标x_a,y_a和宽高w_a,h_a
所以,偏移量:
△x=(x -x_a)/w_a △y=(y -y_a)/h_a
△w=log(w /w_a) △h=log(h /h_a)
通过ground truth box与预测的anchor box之间的差异来进行学习,从而是RPN网络中的权重能够学习到预测box的能力
接着进一步对Anchors进行越界剔除和使用nms非最大值抑制,剔除掉重叠的框;比如,设定IoU为0.7的阈值,即仅保留覆盖率不超过0.7的局部最大分数的box(粗筛)。最后留下大约2000个anchor,然后再取前N个box(比如300个);这样,进入到下一层ROI Pooling时region proposal大约只有300个。
参考文献:
6. viola jones人脸检测原理
Viola-jones人脸检测算法是一种基于滑动窗口的目标检测算法,但它却克服了滑动窗口检测带来的低效问题,可以用于实时人脸检测,主要归功于以下三点:
我参考论文[1]实现了Viola Jones中提到的attention cascade检测框架,此处是 github传送门 。
下面进一步详细介绍整个检测原理。
基于滑窗的目标检测基本原理很简单,首先构建一个classifier(分类器),以人脸检测为例,分类器的工作是判断给定大小的图像的是否为人脸,用该分类器从左至右从上到下扫描整幅图像,扫描获取的部分图像称为子窗(文章中子窗大小为24x24像素),当分类器判断子窗是人脸时,即完成了人脸检测。
这样处理有个问题,如果图像中包含的人脸变大了,此时采用固定大小的子窗就无法进行检测。通常有两种解决方法,1. 采用image-pyramid(图像金字塔),也就是通过resize获得多种不同大小图像并堆叠在一起,用固定大小分类器同时对所有图像进行扫描;2. 采用不同大小的分类器进行扫描。文章中用到的是第二种方法,尽管如此,虽然避免了调整图像大小带来的计算开销,但不同大小的分类器意味着有更多子窗需要进行处理。
如何构建一个足够快的分类器来对每个子窗进行快速判断。
分类器的构建有两种方式,一种是pixel-based(基于像素),另一种是feature-based(基于特征)。当把神经网络作为图像分类器时,输入是图像的像素值,即基于像素的分类器。用图像像素作为输入不包含任何和待分类目标有关的特定信息,往往训练这种分类器需要大量数据,并且分类过程较慢。基于特征的分类器就是先针对图像进行特征提取(HOG特征,SIFT特征等),再利用获取的特征进行分类。这种分类器不需要大量训练数据,且计算量一般会在特征计算部分,相对较小。
文章采用的是基于特征的分类器,选取了一种较为简单的特征即haar-like特征。利用矩形个数对可以将haar-like特征分为三类,分别由两个,三个,和四个 大小相同 的矩形组成。全部列举出来可以分为以下(a)(b)(c)(d)(e)五类(注意是五类不是五个,具体有多少个haar-like特征是由子窗大小决定的)。如下图所示(文章[1]中的图)。
当子窗大小给定后,我们可以用五个参数唯一确定 一个 haar-like特征,即特征种类(a/b/c/d/e),左上角x轴坐标,左上角y轴坐标,矩形的长,矩形的宽。对应的特征值等于位于白色矩形框中像素值总和减去位于黑色矩形框中的像素值总和。文章中用到的子窗大小为24x24像素,可以计算出来总共有162336个特征(把在子窗中所有可能位置和可能大小的特征全部列举出来)。利用haar-like特征进行分类只需两步:
haar-like特征有两个优点,第一是它是scale-invariant(不随图片大小而改变)的,第二是可以通过积分图像快速计算。简单的说下第一点的含义,例如我们用24x24像素的训练样本训练获取一组haar-like特征和对应的门限值,当对图像进行扫描时,子窗大小调整为SxS像素,此时只需将特征中的矩形大小按同样比例进行缩放(门限值同样需要缩放),计算所得的特征值依然是有效的。
积分图像是受卷积的微分性质启发而定义一种数据结构。积分图像定义:
其中 为积分图像, 为原图像。积分图像中 位置处的像素值等于原图中位于 的左侧和上方的所有像素值之和。有了积分图像我们就可以快速计算haar-like特征,以特征(a)为例,如下图所示。
S1到S6是积分图像在这六个顶点上的值。该特征值等于位于A中的像素总和减去位于B中的像素总和,而A中像素总和等于S5+S1-S2-S4,B中像素总和等于S6+S2-S3-S5,并且无论矩形多大,我们总能在固定时间内计算出特征值(6次索引操作和少量的加法乘法计算)。积分图像只需计算一次后续可以一直使用,事实上在算法实现时,我们只需保存样本的积分图像,原图像反而不用保存。
现在找到了一类特征用于构建分类器,和快速计算该类特征的方法。分类器是由一组特征构成的,而不是一个,如何找到一组有效的特征。
文章列举了前人的一些特征选取方法(此处就不列举了),它们虽然取得了一定的效果,但最终选出来的特征数量还是太多。文章将adaBoost算法用于特征选取(创新点),即每次训练的弱分类器的过程看做特征选取的过程,一次从162336个特征中选取一个特征(同时还包括了对应的门限值,极性,加权误差)。
adaboost算法就不详细介绍了,它的基本思想是训练一系列“弱”分类器,组成一个committee(即每个弱分类器都有投票权,但是权重不同,加权误差越小的弱分类器权重越大)。adaboost采用迭代训练方式,给定一个t阶committee,如何寻找第t+1个弱分类器和对应的权重,以最小化在一定分布下的训练样本的加权指数损失。这个优化过程可以转换为对训练样本的分布进行调整(即增大上一轮错误判断的样本的权重,减小正确判断的样本权重),在调整后的样本分布下寻找最小化加权0-1损失的弱分类器并计算对应的加权0-1损失。
可以利用adaboost找到一组特征构成分类器,使得该分类器有极高的准确率和召回率(这种分类器势必会有较大的计算量),这样会导致图像中的每一个子窗都享有同等的计算量,扫描一整幅图会有几十万甚至上百万子窗,总体计算量依然很大。实际上一幅图像中只有极少可能包含人脸的位置是我们感兴趣的,其他不包含人脸的子窗我们希望能够快速筛除,将更精细的计算用于包含人脸的子窗。
文章引入了attention-cascade的机制(注意力级联),即训练多个分类器进行级联,替代单一的分类器。结构如下图所示(文章[3]中的图)。
上图所示的分类器有三级,上一级的输出是下一级的输入,只有预测为正的样本才能传递给下一级,预测为负的样本直接舍弃。大部分非人脸子窗往往在前几级分类器就被舍弃,这样使得扫描每个子窗所需的平均计算量大大减小。
分类器是一级一级训练之后级联起来的,训练分类器时,整个级联分类器的假负率(fpr_overall)有一个训练目标(文章[1]中设置为10e-7),同时每一级有一对训练目标,即假正率和假负率。每级分类器训练的思想是在假负率极低的情况下(文章[1]中设置为0.005)尽量得到一个较低的假正率(文章中[1]中设置为0.5),即我们保证在正样本尽可能多的通过该级分类器的情况下尽量筛除更多的负样本。文章[3]通过一个松弛量来调节假正率和假负率。
下一级用到的训练数据是由所有的正样本和上一级输出的假正样本组成的,这样训练的好处是可以让处于级联后半部分的分类器“看到”更多负样本数据,缺点是训练后期假正样本很难获取,训练时间会比较长。
尽管我们获取了一个级联分类器,但依然不能保证对同一幅图中的一张人脸只会检测到一次(子窗相对人脸有所便宜或者缩放子窗大小都可能导致重复检测),如何消除重复检测,获得更好的检测效果。
文章[3]中说的较为简略,主要是针对检测框构建并查集,并对并查集中的候选框求平均得出最终的检测框。
文章[1]中是采用连通分量算法,计算每种大小检测框的置信度,根据置信度选取最终结果,但前提是检测器在图像中扫描的步进必须是1个像素,处理时间可能会比较长。
只能用于正脸检测,如果人脸朝屏幕内外或者在屏幕平面上旋转均有可能失效
在背景较亮,人脸较暗的情况下可能失效。
在有遮挡的情况下大概率失效。
7. 图像配准的灰度信息
互相关法是最基本的基于灰度统计的图像配准的方法,通常被用于进行模板匹配和模式识别。它是一种匹配度量,通过计算模板图像和搜索窗口之间的互相关值,来确定匹配的程度,互相关值最大时的搜索窗口位置决定了模板图像在待配准图像中的位置。
设A图像为参考图像或基准图像,表示为 ,B为要进行校正后与A配准的图像,表示为 ,在A图像中选择几块包含特征信息丰富的小区域 作模板 ,在 图像重叠部分选择一个重叠区域作为模板的搜索区域 ,并使得 ,即 ,如图14-3所示。然后把每一个模板 放在与其对应的搜索区中,通过两者的相对移动,在逐行逐列的每个位置上,计算 与其覆盖的搜索区 中那部分之间的相似性,产生出表明两者相似程度最大的函数值的位置 。设在待配准图像B搜索到的相似区域为 ,再以 为模板,再用同样的方法在参考图像中去搜索相似程度最大的函数值的区域 ,设定一个阈值Z,如果 ,则认为 和 重合,B图像中的位置 就是B图像与A图像 相匹配的位置;反之,则认为特征区域匹配不正确,即伪匹配。两幅图像之间的相似度评测标准,可以采用不同的方法,主要有下面三种:
14-3 模板匹配示意图图
Fig.14-3 Sample image of template matching
A. 均方和
(14-7)
B. 兰氏距离
(14-8)
C.归一化标准相关系数
(14-9)
其中,在定义式中,
表示的是模板子图像中第 行和第 列的像素的灰度值;
是匹配图像中参考点 处的参考子图像上的第 行和第 列的像素的灰度值;
和 分别代表两个子图像内像素灰度的均值;
而定义式的左边各自代表模板子图像 和另一个图像中的参考点 处的子图像 的相似性测度。
这三个公式中,前两个的极小值代表了可能的匹配位置,后一个公式的极大值代表了可能的匹配位置。其它的一些评测标准都是由这些基本的评测标准引申出来的。如相关系数和标准相关系数都是归一化标准相关系数的简化形式,从本质上都是相同的。
序贯相似度检测匹配法(SSDA)
序贯相似度检测匹配法(Sequential Similarity Detection Algorithms,SSDA)是由Barnea等人提出来的。SSDA方法的最主要的特点是处理速度快。该方法先选择一个简单的固定门限T,若在某点上计算两幅图像残差和的过程中,残差和大于该固定门限T,就认为当前点不是匹配点,从而终止当前的残差和的计算,转向别的点去计算残差和,最后认为残差和增长最慢的点就是匹配点。 这种方法的基本思想是基于对误差的积累进行分析。所以对于大部分非匹配点来说,只需计算模板中的前几个像素点,而只有匹配点附近的点才需要计算整个模板。这样平均起来每一点的运算次数将远远小于实测图像的点数,从而达到减少整个匹配过程计算量的目的。
在SSDA算法中,参考图像与待配准图像之间的相似度评测标准是通过函数 来度量的,公式如下:
(14-10)
其中残差和 ,坐标是从待配准图像中,随机抽取得到的非重复的点坐标序列。 越大,表示误差增长越慢,即两幅图像越相似。这种方法的关键是阈值T的选择,它不仅影响到算法的运算速度,同时还影响到算法的匹配精度。 交互信息法最初是Viola等人于1995年把交互信息引入到图像配准的领域的,它是基于信息理论的交互信息相似性准则。初衷是为了解决多模态医学图像的配准问题。
交互信息用来比较两幅图像的统计依赖性。首先将图像的灰度视作具有独立样本的空间均匀随机过程,相关的随机场可以采用高斯—马尔科夫随机场模型建立,用统计特征及概率密度函数来描述图像的统计性质。交互信息是两个随机变量A和B之间统计相关性的量度,或是一个变量包含另一个变量的信息量的量度。
交互信息 是用A和B的个体熵 和 和联合熵 来表示:
(14-11)
其中:
这里 分别为随机变量A和B的边缘概率密度; 为两个随机变量的联合概率密度分布。交互信息用于图像配准的关键思想是:如果两幅图像达到匹配,它们的交互信息达到最大值。在图像配准应用中,通常联合概率密度和边缘概率密度可以用两幅图像重叠区域的联合概率直方图和边缘概率直方图来估计,或者用Parzen窗概率密度估计法来估计,从而来计算交互信息。
交互信息图像配准方法一经提出,有不少基于此类的研究,尤其在医学图像的配准问题上。比如将交互信息和梯度结合起来改善其极值性能的算法、多分辨率图像金字塔法等等。但交互信息是建立在概率密度估计的基础上的,有时需要建立参数化的概率密度模型,它要求的计算量很大,并且要求图像之间有很大的重叠区域,由此函数可能出现病态,且有大量的局部极值。
8. 图像处理
第三章 图像处理
输出图像的像素值仅仅由输入图像的像素值决定。
1.1 像素变换
根据像素产生输出像素,注意,这里的像素可以是多副图片的像素。
1.2 颜色变换
彩色图像的各通道间具有很强的相关性。
1.3 合成和映射
将前景对象从图像背景中提取出来,被称为抠图;将对象插入另一图像被称为合成。
1.4 直方图均衡化
对比度和亮度参数可以提升图像的外观,为了自动调节这两个参数,有两种方法,一种方法是寻找图像中最亮的值和最暗的值,将它们映射到纯白和纯黑,另一种方法是寻找图像的像素平均值,将其作为像素的中间灰度值,然后充满范围尽量达到可显示的值。
局部自适应直方图均衡化,对于不同的区域采用不同的均衡化方法。缺点是会产生区块效应,即块的边界处亮度不连续,为了消除这一效应,常采用移动窗口,或者在块与块之间的转换函数进行平滑插值。
1.5 应用:色调调整
点算子的常用领域是对照片的对比度和色调进行操作。
与点算子相对应的邻域算子是根据选定像素及周围的像素来决定该像素的 输出。邻域算子不仅用于局部色调调整,还用于图像平滑和锐化,图像的去噪。
邻域算子的重要概念是卷积和相关,它们都是线性移不变算子,满足叠加原理和移位不变原理。
填塞,当卷积核超出图像边界时,会产生边界效应。有多种填塞方法,0填塞,常数填塞,夹取填塞,重叠填塞,镜像填塞,延长。
2.1 可分滤波器
如果一个卷积运算可以分解为一维行向量卷积和一维列向量卷积,则称该卷积核可分离。2D核函数可以看作一个矩阵K,当且仅当K的第一个奇异值为0时,K可分离。
2.2 线性滤波器举例
最简单的滤波器是移动平均或方框滤波器,其次是双线性滤波器(双线性核),高斯滤波器(高斯核),以上均为低通核,模糊核,平滑核。对于这些核函数效果的度量采用傅里叶分析。还有Sobel算子和角点算子。
2.3 带通和导向滤波器
Sobel算子是带方向的滤波器的近似,先用高斯核平滑图像,再用方向导数(拉普拉斯算子)作用于图像,得到导向滤波器,导向具有潜在的局部性以及很好的尺度空间特性。导向滤波器常用来构造特征描述子和边缘检测器,线性结构通常被认为是类似边缘的。
区域求和表是指一定区域内所有像素值的和,又称为积分图像,它的有效计算方法是递归算法(光栅扫描算法),区域求和表用于对其他卷积核的近似,人脸检测中的多尺度特征,以及立体视觉中的差分平方和的计算。
递归滤波器称为无限脉冲响应(IIR),有时用于二维距离函数和连通量的计算,也可计算大面积的平滑计算。
3.1 非线性滤波器
中值滤波可以去除散粒噪声,它的另一个优点是保边平滑,即在滤除高频噪声时,边缘不容易被柔化。
双边滤波器思想的精髓在于,抑制与中心像素值差别较大的像素,而不是抑制固定百分比 的像素。在加权滤波器的基础上,对权重系数进行了控制,即取决于定义域核(高斯核)和值域核(与中心像素值的相似度),两者相乘得到双边滤波器核。
迭代自适应平滑核各项异性扩散。
3.2 形态学
非线性滤波常用于二值图像处理,二值图像中最常见的算子是形态学算子,将二值结构元素与二值图像卷积,根据卷积结果的阈值选择二值输出,结构元素可以是任何形状。
常见的形态学操作有膨胀,腐蚀,过半,开运算,闭运算。过半使锐利的角变得平滑,开运算和闭运算去除图像中小的点和孔洞,并使图像平滑。
3.3 距离变换
距离变换通过使用两遍光栅扫描法,快速预计算到曲线或点集的距离,包括城街距离变换和欧氏距离变换。符号距离变换是基本距离变换的扩展,计算了所有像素到边界像素的距离。
3.4 连通域
检测图像的连通量是半全局的图像操作,连通量定义为具有相同输入值的邻接像素的区域,二值或多值图像被分割成连通量形式后,对每个单独区域计算统计量,面积,周长,质心,二阶矩,可用于区域排序和区域匹配。
傅里叶变换用于对滤波器的频域特征进行分析,FFT能快速实现大尺度核的卷积。
思想:为了分析滤波器的频率特征,将一个已知频率的正弦波通过滤波器,观察正弦波变弱的程度。傅里叶变换可认为是输入信号为正弦信号s(x),经过滤波器h(x)后,产生的输出响应为正弦信号o(x)=s(x)*h(x),即两者的卷积。傅里叶变换是对每个频率的幅度和相位响应的简单罗列。傅里叶变换不仅可以用于滤波器,还能用于信号和图像。
傅里叶变换的性质:叠加,平移,反向,卷积,相关,乘,微分,定义域缩放,实值图像,Parseval定理。
4.1 傅里叶变换对
常见的傅里叶变换对,连续的和离散的。方便进行傅里叶变换。
高频成分将在降采样中导致混叠。
4.2 二维傅里叶变换
为了对二维图像及滤波器进行处理,提出了二维傅里叶变换,与一维傅里叶变换类似,只不过用向量代替标量,用向量内积代替乘法。
4.3 维纳滤波器
傅里叶变换还可用于分析一类图像整体的频谱,维纳滤波器应运而生。假定这类图像位于随机噪声场中,每个频率的期望幅度通过功率谱给出,信号功率谱捕获了空间统计量的一阶描述。维纳滤波器适用于去除功率谱为P的图像噪声的滤波器。
维纳滤波器的性质,对于低频具有 单位增益,对于高频,具有减弱的效果。
离散余弦变换(DCT)常用于处理以块为单位的图像压缩,它的计算方法是将以N为宽度的块内的像素与一系列不同频率的余弦值进行点积来实现。
DCT变换的实质是对自然图像中一些小的区域的最优KL分解(PCA主成分分析的近似),KL能有效对信号去相关。
小波算法和DCT交叠变种能有效去除区块效应。
4.4 应用:锐化,模糊,去噪
锐化和去噪声能有效增强图像,传统的方法是采用线性滤波算子,现在广泛采用非线性滤波算子,例如加权中值和双边滤波器,各向异性扩散和非局部均值,以及变分方法。
度量图像去噪算法效果时,一般采用峰值信噪比(PNSR),结构相似性(SSIM)索引。
迄今为止所研究的图像变换输出图像大小均等于输入图像的大小,为了对不同分辨率的图像进行处理,比如,对小图像进行插值使其与电脑的分辨率相匹配,或者减小图像的大小来加速算法的执行或节省存储空间和传输时间。
由于不知道处理图像所需的分辨率,故由多幅不同的图像构建图像金字塔,从而进行多尺度的识别和编辑操作。改变图像分辨率较好的滤波器是插值滤波器和降采样滤波器。
5.1 插值
为将图像变大到较高分辨率,需要用插值核来卷积图像,二次插值常用方法是双线性插值,双三次插值,窗函数。窗函数被认为是品质最高的插值器,因为它既可以保留低分辨率图像中的细节,又可以避免混叠。
5.2 降采样
降采样是为了降低图像分辨率,先用低通滤波器卷积图像,避免混叠,再保持第r个样例。常用的降采样滤波器有线性滤波器,二次滤波器,三次滤波器,窗余弦滤波器,QMF-9滤波器,JPEG2000滤波器。
5.3 多分辨率表示
通过降采样和插值算法,能够对图像建立完整的图像金字塔,金字塔可以加速由粗到精的搜索算法,以便在不同的尺度上寻找物体和模式,或进行多分辨率融合操作。
计算机视觉中最有名的金字塔是拉普拉斯金字塔,采用大小为2因子对原图像进行模糊和二次采样,并将它存储在金字塔的下一级。
5.4 小波变换
小波是在空间域和频率域都定位一个信号的滤波器,并且是在不同层次的尺度上定义的。小波可以进行多尺度有向滤波和去噪。与常规的金字塔相比,小波具有更好的方向选择性,并提供了紧致框架。
提升小波被称为第二代小波,很容易适应非常规采样拓扑,还有导向可移位多尺度变换,它们的表述不仅是过完备的,而且是方向选择的。
5.5 应用:图像融合
拉普拉斯金字塔的应用,混合合成图像。要产生混合图像,每个原图像先分解成它自己的拉普拉斯金字塔,之后每个带被乘以一个大小正比于金字塔级别的平滑加权函数 。最简单的方法是建立一个二值掩膜图像,根据此图像产生一个高斯金字塔,再将拉普拉斯金字塔和高斯掩膜,这两个带权金字塔的和产生最终图像。
相对于点操作改变了图像的值域范围,几何变换关注于改变图像的定义域。原先采用的方法是全局参数化2D变换,之后的注意力将转向基于网格的局部变形等更多通用变形。
6.1 参数变换
参数化变换对整幅图像进行全局变换,其中变换的行为由少量的参数控制,反向卷绕或反向映射的性能优于前向卷绕,主要在于其能够避免空洞和非整数位置重采样的问题。而且可以用高质量的滤波器来控制混叠。
图像卷绕问题可形式化为给定一个从目标像素x'到原像素x的映射来重采样一副原图像。类似的反向法应用场合有光流法预测光流以及矫正透镜的径向畸变。
重采样过程的插值滤波器有,二次插值,三次插值,窗插值,二次插值追求速度,三次插值和窗插值追求视觉品质。
MIP映射是一种纹理映射的快速预滤波图像工具。
MIP图是标准的图像金字塔,每层用一个高质量的滤波器滤波而不是低质量的近似,重采样时,需要预估重采样率r。
椭圆带权平均滤波器(EWA),各向异性滤波,多通变换。
有向二位滤波和重采样操作可以用一系列一维重采样和剪切变换来近似,使用一系列一维变换的优点是它们比大的,不可分离的二位滤波核更有效。
6.2 基于网格扭曲
为了获得更自由的局部变形,产生了网格卷绕。稀疏控制点,稠密集,有向直线分割,位移场的确定。
6.3 应用:基于特征的形态学
卷绕常用于改变单幅图像的外观以形成动画,也可用于多幅图像的融合以产生强大的变形效果,在两幅图像之间进行简单的渐隐渐显会导致鬼影,但采用图像卷绕建立了良好的对应关系,相应的特征便会对齐。
用一些优化准则明确表达想要变换的目标,再找到或推断出这个准则的解决办法。正则化和变分法,构建一个描述解特性的连续全局能量函数,然后用稀疏线性系统或相关迭代方法找到最小能量解,贝叶斯统计学对产生输入图像的有噪声的测量过程和关于解空间的先验假设进行建模,通常用马尔科夫随机场进行编码。常见示例有散列数据的表面插值,图像去噪和缺失区域恢复,将图像分为前景和背景区域。
7.1 正则化
正则化理论试图用模型来拟合严重欠约束解空间的数据。即用一个平滑的表面穿过或是靠近一个测量数据点集合的问题。这样的问题是病态的和不适定的。这样由采样数据点d(xi,yi)恢复完整图像f(x,y)的问题被称为逆问题。
为了定义平滑解,常在解空间上定义一个范数,对于一维函数,函数一阶导数的平方进行积分,或对函数二阶导数的平方进行积分,这种能量度量是泛函的样例,是将函数映射到标量值的算子,这种方法被称为变分法,用于度量函数的变化(非平滑性)。
7.2 马尔科夫随机场
7.3 应用:图像复原
9. CV算法:金字塔(Image Pyramid)
参考资料:
Image Pyramid
斯坦福CS131-1718作业7
CS486-Lecture 11:LoG and DoG Filters
图像通常在空间域上来进行表示,在空间域上我们可以进行很多滤波操作,滤波一般是操作点及其附近的信息。但是图片包含很多复杂的信息,通常很难在空间域上就处理好。
我们还可以在频域上对图像进行操作。但频域主要的问题会混合从图片其他地方的频率信息,这叫做“局部性的损失”(loss of locality),大部分情况下,我们不想在我们面部细节上混淆一些背景中草的信息。
为了利用空间域和频域的信息,我们发明了空频域(spatial-frequency),可以既分离频率成分,又可以保留局部信息。
图像金字塔实际上将图片表示为一系列不同频率的图像,这些图像保留了不同的细节信息,因为这个特性,又叫多分辨率或者多尺度。
上一步的金字塔相减得到,注意右边黑黑的才是。因为G1是要比G0小的,所以G0要扩大后再相减。L0实际上就是被滤掉的高频信息,现在回来啦。L0更细节,更高频。
金字塔就是另外一种表示图片的方式,结合了空间域和频域的优点。
冈萨雷斯书上说,在模式是被中,高分辨率的图像用来识别一些细节,低分辨率的图像用来识别一些大的结构。
在HOG识别人脸中,人脸因为大小不同可能跟计算出来错误,所以这里缩放多张图片,依次计算,得到分数最大的才是。
10. 特征金字塔网络FPN
姓名:郄心怡 学号:19020100205 学院:电子工程学院
【原文链接】 https://zhuanlan.hu.com/p/39185919
【嵌牛导读】本文对特征金字塔网络FPN做了一个简单介绍
【嵌牛鼻子】特征金字塔网络FPN
【嵌牛提问】什么是特征金字塔网络FPN?
【嵌牛正文】
这里介绍的文章是来自Facebook的特征金字塔网络Feature Pyramid Networks(FPN)。FPN主要解决的是物体检测中的多尺度问题,通过简单的网络连接改变,在基本不增加原有模型计算量情况下,大幅度提升了小物体检测的性能。我们将从论文背景,论文思想,结果与结论几方面探讨此论文。
在物体检测里面,有限计算量情况下,网络的深度(对应到感受野)与stride通常是一对矛盾的东西,常用的网络结构对应的stride一般会比较大(如32),而图像中的小物体甚至会小于stride的大小,造成的结果就是小物体的检测性能急剧下降。传统解决这个问题的思路包括:
(1)多尺度训练和测试,又称图像金字塔,如图1(a)所示。目前几乎所有在ImageNet和COCO检测任务上取得好成绩的方法都使用了图像金字塔方法。然而这样的方法由于很高的时间及计算量消耗,难以在实际中应用。
(2)特征分层,即每层分别预测对应的scale分辨率的检测结果。如图1(c)所示。SSD检测框架采用了类似的思想。这样的方法问题在于直接强行让不同层学习同样的语义信息。而对于卷积神经网络而言,不同深度对应着不同层次的语义特征,浅层网络分辨率高,学的更多是细节特征,深层网络分辨率低,学的更多是语义特征。
因而,目前多尺度的物体检测主要面临的挑战为:
1. 如何学习具有强语义信息的多尺度特征表示?
2. 如何设计通用的特征表示来解决物体检测中的多个子问题?如object proposal, box localization, instance segmentation.
3. 如何高效计算多尺度的特征表示?
本文针对这些问题,提出了特征金字塔网络FPN,如图1(d)所示,网络直接在原来的单网络上做修改,每个分辨率的feature map引入后一分辨率缩放两倍的feature map做element-wise相加的操作。通过这样的连接,每一层预测所用的feature map都融合了不同分辨率、不同语义强度的特征,融合的不同分辨率的feature map分别做对应分辨率大小的物体检测。这样保证了每一层都有合适的分辨率以及强语义特征。同时,由于此方法只是在原网络基础上加上了额外的跨层连接,在实际应用中几乎不增加额外的时间和计算量。作者接下来实验了将FPN应用在Faster RCNN上的性能,在COCO上达到了state-of-the-art的单模型精度。
具体而言,FPN分别在RPN和Fast RCNN两步中起到作用。其中RPN和Fast RCNN分别关注的是召回率和正检率,在这里对比的指标分别为Average Recall(AR)和Average Precision(AP)。分别对比了不同尺度物体检测情况,小中大物体分别用s,m,l表示。
在RPN中,区别于原论文直接在最后的feature map上设置不同尺度和比例的anchor,本文的尺度信息对应于相应的feature map(分别设置面积为32^2, 64^2, 128^2, 256^2, 512^2),比例用类似于原来的方式设置{1:2, 1:1,, 2:1}三种。
与RPN一样,FPN每层feature map加入3*3的卷积及两个相邻的1*1卷积分别做分类和回归的预测。在RPN中,实验对比了FPN不同层feature map卷积参数共享与否,发现共享仍然能达到很好性能,说明特征金字塔使得不同层学到了相同层次的语义特征。RPN网络的实验结果为:
这里FPN对比原来取自conv4和conv5的RPN网络(a)(b),召回率得到了大幅度提升,尤其在中物体和小物体上(c)。另外,作者做了变量对比实验,比如只保留横向连接(d),即特征分层网络,性能仅与原RPN差不多,原因就在于不同层之间的语义特征差距较大。另外,试验了砍掉横向连接,只保留自上而下放大feature map做预测结果(e),以及只用最终得到的feature map层(f),均比完整的FPN网络小物体检测AR低10个点左右。说明金字塔特征表示与横向连接都起了很大作用。
实验Fast RCNN时,需要固定FPN+RPN提取的proposal结果。在Fast RCNN里,FPN主要应用于选择提取哪一层的feature map来做ROI pooling。假设特征金字塔结果对应到图像金字塔结果。定义不同feature map集合为{P2, P3, P4, P5},对于输入网络的原图上w*h的ROI,选择的feature map为Pk,其中(224为ImageNet输入图像大小):
类似于RPN的实验,对比了原有网络,以及不同改变FPN结构的Fast RCNN实验,实验结果为:
实验发现FPN筛选ROI区域,同样对于Fast RCNN的小物体检测精度有大幅提升。同时,FPN的每一步都必不可少。
最后,FPN对比整个Faster RCNN的实验结果如下:
对比其他单模型方法结果为:
最后是在FPN基础上,将RPN和Fast RCNN的特征共享,与原Faster CNN一样,精度得到了小幅提升。
FPN+Faster RCNN的方法在COCO数据集上最终达到了最高的单模型精度。
总结起来,本文提出了一种巧妙的特征金字塔连接方法,实验验证对于物体检测非常有效,极大提高了小物体检测性能,同时由于相比于原来的图像金字塔多尺度检测算法速度也得到了很大提升。
Q1:不同深度的feature map为什么可以经过upsample后直接相加?
答:作者解释说这个原因在于我们做了end-to-end的training,因为不同层的参数不是固定的,不同层同时给监督做end-to-end training,所以相加训练出来的东西能够更有效地融合浅层和深层的信息。
Q2:为什么FPN相比去掉深层特征upsample(bottom-up pyramid)对于小物体检测提升明显?(RPN步骤AR从30.5到44.9,Fast RCNN步骤AP从24.9到33.9)
答:作者在poster里给出了这个问题的答案
对于小物体,一方面我们需要高分辨率的feature map更多关注小区域信息,另一方面,如图中的挎包一样,需要更全局的信息更准确判断挎包的存在及位置。
Q3:如果不考虑时间情况下,image pyramid是否可能会比feature pyramid的性能更高?
答:作者觉得经过精细调整训练是可能的,但是image pyramid主要的问题在于时间和空间占用太大,而feature pyramid可以在几乎不增加额外计算量情况下解决多尺度检测问题。