opencv光流(密集光流+稀疏光流) cv.calcOpticalFlowPyrLK & cv2.calcOpticalFlowFarneback python与c++实现

密集光流 cv.calcOpticalFlowFarneback()

类型 算法 相关论文
密集光流 Gunnar-Farneback算法 Two-Frame Motion Estimation Based on Polynomial Expansion

官方代码

# 略修改与注释
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(cv.samples.findFile("test.mp4"))
ret, frame1 = cap.read()
prvs = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[..., 1] = 255
while(1):
    ret, frame2 = cap.read()
    if not ret:
        print('No frames grabbed!')
        break
    next = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)
    flow = cv.calcOpticalFlowFarneback(prvs, next, None, 0.5, 3, 15, 3, 5, 1.2, 0)# 计算光流(只需要前后帧和一些参数即可)

    mag, ang = cv.cartToPolar(flow[..., 0], flow[..., 1])# 转为极坐标
    # 用hsv矩阵 (480, 640, 3) 保存
    hsv[..., 0] = ang*180/np.pi/2
    hsv[..., 2] = cv.normalize(mag, None, 0, 255, cv.NORM_MINMAX)

    bgr = cv.cvtColor(hsv, cv.COLOR_HSV2BGR)# 转为彩色图像
    cv.imshow("original frame", frame2)
    cv.imshow('optical vis', bgr)
    k = cv.waitKey(30) & 0xff
    # if k == 27:
    #     break
    # elif k == ord('s'):
    #     cv.imwrite('opticalfb.png', frame2)
    #     cv.imwrite('opticalhsv.png', bgr)
    prvs = next
cv.destroyAllWindows()

opencv光流(密集光流+稀疏光流) cv.calcOpticalFlowPyrLK & cv2.calcOpticalFlowFarneback python与c++实现_第1张图片

可视化的转换

opencv光流(密集光流+稀疏光流) cv.calcOpticalFlowPyrLK & cv2.calcOpticalFlowFarneback python与c++实现_第2张图片

H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。
纯度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。
V表示色彩的明亮程度,范围从0到1。有一点要注意:它和光强度之间并没有直接的联系。

c++实现


#include 
#include 
#include 
#include 
#include 
#include 
#include //https://blog.csdn.net/weixin_44312186/article/details/89000922
using namespace cv;
using namespace std;
int main()
{
	cv::namedWindow("ori", WINDOW_NORMAL);//WINDOW_NORMAL 用户可以改变这个窗口大小
	cv::namedWindow("frame2", WINDOW_NORMAL);



	VideoCapture capture(samples::findFile("C:\\Users\\admin\\Desktop\\flasktest\\train6001.mp4"));//https://docs.opencv.org/4.x/d6/dba/group__core__utils__samples.html#ga3a33b00033b46c698ff6340d95569c13
	if (!capture.isOpened()) {
		//error in opening the video input
		cerr << "Unable to open file!" << endl;
		return 0;
	}
	Mat frame1, prvs;// https://docs.opencv.org/4.x/d3/d63/classcv_1_1Mat.html
	Mat _frame1;
	capture >> _frame1;
	
	cv::resize(_frame1, frame1, cv::Size(640, 480), 0, 0, cv::INTER_AREA);//https://stackoverflow.com/questions/17533101/resize-a-matrix-after-created-it-in-opencv
	

	cvtColor(frame1, prvs, COLOR_BGR2GRAY);
	while (true) {
		Mat frame2, next;
		Mat _frame2;
		capture >> _frame2;
		
		cv::resize(_frame2, frame2, cv::Size(640, 480), 0, 0, cv::INTER_AREA);

		if (frame2.empty())
			break;
		cvtColor(frame2, next, COLOR_BGR2GRAY);
        //计算光流
		Mat flow(prvs.size(), CV_32FC2);
		calcOpticalFlowFarneback(prvs, next, flow, 0.5, 3, 15, 3, 5, 1.2, 0);
		// visualization
		Mat flow_parts[2];
		split(flow, flow_parts);
		Mat magnitude, angle, magn_norm;
		cartToPolar(flow_parts[0], flow_parts[1], magnitude, angle, true);
		normalize(magnitude, magn_norm, 0.0f, 1.0f, NORM_MINMAX);
		angle *= ((1.f / 360.f) * (180.f / 255.f));
		
		//build hsv image
		Mat _hsv[3], hsv, hsv8, bgr;
		_hsv[0] = angle;
		_hsv[1] = Mat::ones(angle.size(), CV_32F);
		_hsv[2] = magn_norm;
		merge(_hsv, 3, hsv);
		hsv.convertTo(hsv8, CV_8U, 255.0);
		cvtColor(hsv8, bgr, COLOR_HSV2BGR);
		imshow("frame2", bgr);
		imshow("ori", next);
		int keyboard = waitKey(30);
		if (keyboard == 'q' || keyboard == 27)
			break;
		prvs = next;
	}
}

稀疏光流 cv.calcOpticalFlowPyrLK()

类型 算法 相关论文
稀疏光流 Lucas Kanade(LK)算法 An iterative image registration technique with an application to stereo vision+Generalized Image Matching by the Method of Differences

官方代码

# 略修改与注释
import numpy as np
import cv2 as cv
import argparse

parser = argparse.ArgumentParser(description='This sample demonstrates Lucas-Kanade Optical Flow calculation. \
                                              The example file can be downloaded from: \
                                              https://www.bogotobogo.com/python/OpenCV_Python/images/mean_shift_tracking/slow_traffic_small.mp4')
# parser.add_argument('image', type=str, help='path to image file')
parser.add_argument('--image', type=str,default='test.mp4', help='path to image file')
args = parser.parse_args()

cap = cv.VideoCapture(args.image)

# params for ShiTomasi corner detection
feature_params = dict( maxCorners = 100,
                       qualityLevel = 0.3,
                       minDistance = 7,
                       blockSize = 7 )

# Parameters for lucas kanade optical flow
lk_params = dict( winSize  = (15, 15),
                  maxLevel = 2,
                  criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 0.03))

# Create some random colors
color = np.random.randint(0, 255, (100, 3))

# Take first frame and find corners in it
ret, old_frame = cap.read()
old_gray = cv.cvtColor(old_frame, cv.COLOR_BGR2GRAY)
p0 = cv.goodFeaturesToTrack(old_gray, mask = None, **feature_params)

# Create a mask image for drawing purposes
mask = np.zeros_like(old_frame)

while(1):
    ret, frame = cap.read()
    if not ret:
        print('No frames grabbed!')
        break

    frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

    # calculate optical flow
    p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # Select good points
    if p1 is not None:
        good_new = p1[st==1]
        good_old = p0[st==1]

    # draw the tracks
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        mask = cv.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)
        frame = cv.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)
    img = cv.add(frame, mask)

    cv.imshow('frame', img)
    k = cv.waitKey(30) & 0xff
    if k == 27:
        break

    # Now update the previous frame and previous points
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

cv.destroyAllWindows()

参考与更多

官方介绍

你可能感兴趣的:(算法,opencv,python,c++)