【C++ OpenCV】图像金字塔中计算Lucas-Kanande光流算法

在学习图像金字塔代码之前,需要先看角点检测的的代码,因为在图像金字塔中,检测的点用的就是角点

1.角点检测

1.1角点检测代码

void cv::goodFeaturesToTrack(
		cv::InputArray image, 			// 输入图像(CV_8UC1 CV_32FC1)
		cv::OutputArray corners,		// 输出角点vector
		int maxCorners, 				// 最大角点数目
		double qualityLevel, 			// 质量水平系数(小于1.0的正数,一般在0.01-0.1之间)
		double minDistance, 			// 最小距离,小于此距离的点忽略
		cv::InputArray mask = noArray(), // mask=0的点忽略
		int blockSize = 3, 				// 使用的邻域数
		bool useHarrisDetector = false, // false ='Shi Tomasi metric'
		double k = 0.04 				// Harris角点检测时使用
	);

1.2角点检测参数解析:

第一个参数是输入图像(8位或32位单通道图)。

第二个参数是检测到的所有角点,类型为vector或数组,由实际给定的参数类型而定。如果是vector,那么它应该是一个包含cv::Point2f的vector对象;如果类型是cv::Mat,那么它的每一行对应一个角点,点的x、y位置分别是两列。

第三个参数用于限定检测到的点数的最大值。

第四个参数表示检测到的角点的质量水平(通常是0.10到0.01之间的数值,不能大于1.0)。

第五个参数用于区分相邻两个角点的最小距离(小于这个距离得点将进行合并)。

第六个参数是mask,如果指定,它的维度必须和输入图像一致,且在mask值为0处不进行角点检测。

第七个参数是blockSize,表示在计算角点时参与运算的区域大小,常用值为3,但是如果图像的分辨率较高则可以考虑使用较大一点的值。

第八个参数用于指定角点检测的方法,如果是true则使用Harris角点检测,false则使用Shi Tomasi算法。

第九个参数是在使用Harris算法时使用,最好使用默认值0.04。

1.3角点检测代码实例:

cv::Mat image_color = cv::imread("house.jpg", cv::IMREAD_COLOR);
 
	//使用灰度图像进行角点检测
	cv::Mat image_gray;
	cv::cvtColor(image_color, image_gray, cv::COLOR_BGR2GRAY);
 
	//设置角点检测参数
	std::vector<cv::Point2f> corners;
	int max_corners = 200;
	double quality_level = 0.01;
	double min_distance = 3.0;
	int block_size = 3;
	bool use_harris = false;
	double k = 0.04;
 
	//角点检测
	cv::goodFeaturesToTrack(
		image_gray, 
		corners, 
		max_corners, 
		quality_level, 
		min_distance, 
		cv::Mat(), 
		block_size, 
		use_harris, 
		k);
 
	//将检测到的角点绘制到原图上
	for (int i = 0; i < corners.size(); i++)
	{
		cv::circle(image_color, corners[i], 1, cv::Scalar(0, 0, 255), 2, 8, 0);
	}
 
	cv::imshow("house corner", image_color);
	cv::waitKey(0);
	return;

2金字塔Lucas-Kanande

2.1金字塔Lucas-Kanande代码

void calcOpticallFlowPyrLK (
    InputArray prevImg, 
    InputArray nextImg, 
    InputArray prevPts, 
    InputOutputArray nextPts, 
    OutputArray status, 
    OutputArray err,
    Size winSize = Size(21,21), 
    int maxLevel = 3, 
    TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), 
    int flags = 0, 
    double minEigThreshold = 1e-4
);

2.2金字塔Lucas-Kanande代码参数解析:

在这里插入图片描述

2.3金字塔Lucas-Kanande代码实例:

#include <iostream>
#include <vector>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
 
const int MAX_CORNERS = 500;
int main()
{
	cv::Mat imageA = cv::imread("img00001.png", 1);
	cv::Mat imageB = cv::imread("img00002.png", 1);
 
	//使用灰度图像进行角点检测
	
	//转灰度图像
	cv::Mat imageA_gray, imageB_gray;
	cv::cvtColor(imageA, imageA_gray, cv::COLOR_BGR2GRAY);
	cv::cvtColor(imageB, imageB_gray, cv::COLOR_BGR2GRAY);
	 
	//设置角点检测参数
	std::vector<cv::Point2f> cornersA;
	int max_corners = MAX_CORNERS;
	double quality_level = 0.01;
	double min_distance = 5.0;
	int block_size = 3;
	bool use_harris = false;
	double k = 0.04;
 
	//角点检测
	cv::goodFeaturesToTrack(
		imageA_gray,
		cornersA,
		max_corners,
		quality_level,
		min_distance,
		cv::Mat(),
		block_size,
		use_harris,
		k);
	
	cv::Size winSize(10, 10);
	cv::TermCriteria criteria = cv::TermCriteria(
					cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS,
					20,
					0.03);
 
	//亚像素检测
	cv::cornerSubPix(imageA_gray, cornersA, winSize, cv::Size(-1, -1), criteria);
 
	
	std::vector<cv::Point2f> cornersB;
	std::vector<uchar> status;
	std::vector<float> err;
	cv::calcOpticalFlowPyrLK(imageA_gray, imageB_gray, cornersA, cornersB, status, err, winSize, 5, criteria, 0, 0.001);
 
	cv::Mat	imageC = imageB.clone();
	for( int i = 0; i< cornersA.size(); i++ ) 
	{
        if(status[i] == '0') continue;
        cv::Point p0 = cv::Point(cvRound(cornersA[i].x), cvRound(cornersA[i].y ));
        cv::Point p1 = cv::Point(cvRound(cornersB[i].x), cvRound( cornersB[i].y));
        line( imageC, p0, p1, cv::Scalar(0,0,255), 1, CV_AA);
    }
    
    cv::imshow("ImageA",imageA);
    cv::imshow("ImageB",imageB);
    cv::imshow("LKpyr_OpticalFlow",imageC);
 
	cv::waitKey(0);
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Lucas-Kanade光流算法是一种基于局部区域的光流算法,它假设图像任意两帧之间的像素值变化是平滑的,然后使用局部区域内的像素值变化来估计每个像素的运动向量。在本文,我们将介绍如何在OpenCV自实现Lucas-Kanade光流算法。 步骤一:读取图像 首先,我们需要读取两张待计算光流的图像。在本例,我们将使用名为“frame1”和“frame2”的两张图像。 Mat frame1 = imread("frame1.jpg"); Mat frame2 = imread("frame2.jpg"); 步骤二:提取关键点 接下来,我们需要从两个图像提取关键点。我们可以使用OpenCV的FAST或SIFT等算法来提取关键点。在本例,我们将使用FAST算法。 vector<KeyPoint> keypoints1, keypoints2; int threshold = 20; // 设置FAST算法的阈值 bool nonmaxSuppression = true; // 设置是否进行非极大值抑制 FAST(frame1, keypoints1, threshold, nonmaxSuppression); FAST(frame2, keypoints2, threshold, nonmaxSuppression); 步骤三:计算光流 现在我们已经提取了关键点,接下来我们需要计算这些关键点的光流向量。我们可以使用OpenCV的calcOpticalFlowPyrLK函数来计算光流向量。该函数使用金字塔表示法和Lucas-Kanade算法计算光流向量。 vector<uchar> status; vector<float> err; Size winSize = Size(21, 21); // 设置光流计算窗口的大小 int maxLevel = 3; // 设置金字塔的最大层数 TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01); // 设置终止条件 calcOpticalFlowPyrLK(frame1, frame2, keypoints1, keypoints2, status, err, winSize, maxLevel, criteria); 步骤四:绘制光流 最后,我们可以将光流向量绘制在第一张图像上,以便我们可以观察到光流的效果。 for (int i = 0; i < keypoints1.size(); i++) { if (status[i]) { Point2f p1 = keypoints1[i].pt; Point2f p2 = keypoints2[i].pt; line(frame1, p1, p2, Scalar(0, 0, 255), 2); } } imshow("Optical Flow", frame1); 完整代码:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值