光流法检测材料和目标的微变形区域,计算像素位移和应力应变
光流法的前提假设:
(1)相邻帧之间的亮度保持恒定,不适合现实光照环境下测试;
(2)相邻视频帧的取帧时间连续,相邻帧之间物体的运动比较“微小”,检测目标属于微变形,微运动;
(3)保持空间一致性;即,同一子图像的像素点具有相同的运动。
应用场景:
(1)物体在运动,相机是静止的;
(2)相机在运动,物体是静止的;
(3)两者都在运动;
本实验是在第一种情况下实现的。
光流法用于目标检测的原理:给图像中的每个像素点赋予一个速度矢量,这样就形成了一个运动矢量场。在某一特定时刻,图像上的点与三维物体上的点一一对应,这种对应关系可以通过投影来计算得到。根据各个像素点的速度矢量特征,可以对图像进行动态分析。如果图像中没有运动目标,则光流矢量在整个图像区域是连续变化的。当图像中有运动物体时,目标和背景存在着相对运动。运动物体所形成的速度矢量必然和背景的速度矢量有所不同,如此便可以计算出运动物体的位置。需要提醒的是,利用光流法进行运动物体检测时,计算量较大,无法保证实时性和实用性。
光流法用于目标跟踪的原理:
(1)对一个连续的视频帧序列进行处理;
(2)针对每一个视频序列,利用一定的目标检测方法,检测可能出现的前景目标;
(3)如果某一帧出现了前景目标,找到其具有代表性的关键特征点(可以随机产生,也可以利用角点来做特征点);
(4)对之后的任意两个相邻视频帧而言,寻找上一帧中出现的关键特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置坐标;
(5)重复(2)~(4)步骤,实现目标的跟踪;
用于光流计算的关键点和关键特征区域可以由广泛的选择,选取角点特征后,通过跟踪角点实现光流计算进而实现跟踪目标;选取目标对象区域中的某一子区域的灰度特征,计算相关系数求得该区域在下一帧中的最佳位置实现目标跟踪;也可以根据目标颜色特征实现跟踪。大多数算法一般都是基于两个关键的假设条件实现目标跟踪,一个是颜色一致假设;一个是微小运动假设。
calcOpticalFlowFarneback(prev_gray, gray, flowdata, 0.5, 3, 15, 3, 5, 1.2, 0);
//BGR渐变色
void drawOpticalFlowHF(const Mat &flowdata, Mat& image, int step) {
vector<float> v1;
vector<float> v2;
for (int row = 0; row < image.rows; row++) {
for (int col = 0; col < image.cols; col++) {
const Point2f fxy = flowdata.at<Point2f>(row, col);
v1.push_back(fxy.x);
v2.push_back(fxy.y);
}
}
vector<float>::iterator biggest = max_element(begin(v1), end(v1));
cout << "Max element is " << *biggest << "at position " << distance(begin(v1), biggest) << endl;
auto smallest = std::min_element(begin(v1), end(v1));
cout << "min element is " << *smallest << " at position " << distance(begin(v1), smallest) << endl;
vector<float>::iterator biggest2 = max_element(begin(v2), end(v2));
cout << "Max element is " << *biggest2 << "at position " << distance(begin(v2), biggest2) << endl;
auto smallest2 = std::min_element(begin(v2), end(v2));
cout << "min element is " << *smallest2 << " at position " << distance(begin(v2), smallest2) << endl;
float r, g, b;
test_num = *biggest;
for (int row = 0; row < image.rows; row++) {
for (int col = 0; col < image.cols; col++) {
const Point2f fxy = flowdata.at<Point2f>(row, col);
//v1.push_back(fxy.x);
//v2.push_back(fxy.y);
if (fxy.x > 0 || fxy.y > 0) {
if ((4.35682-abs(fxy.x))>3 && abs(fxy.x)<4.35682)
{
//B、G、R根据极值求出对应格式
}
else if ((4.35682 - abs(fxy.x))>2.4 && (4.35682 - abs(fxy.x))<3)
{
//B、G、R根据极值求出对应格式
}
else if ((4.35682 - abs(fxy.x))>1.8 &&(4.35682 - abs(fxy.x))<2.4)
{
//B、G、R根据极值求出对应格式
}
else if ((4.35682 - abs(fxy.x))>1.2 && (4.35682 - abs(fxy.x))<1.8)
{
//B、G、R根据极值求出对应格式
}
else
{
//B、G、R根据极值求出对应格式
}
line(image, Point(col, row), Point(cvRound(col + fxy.x), cvRound(row + fxy.y)), Scalar(b*255, g*255, r*255), 2, 8, 0);
//circle(image, Point(col, row), 2, Scalar(b * 255, g * 255, r * 255), -1);
}
/*else if (fxy.x > 3 || fxy.y > 3) {
line(image, Point(col, row), Point(cvRound(col + fxy.x), cvRound(row + fxy.y)), Scalar(0, 255, 0), 2, 8, 0);
//circle(image, Point(col, row), 2, Scalar(0, 255, 0), -1);
}*/
}
}
}
测试结果: