日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

opencv求两张图像光流_光流(optical flow)和openCV中实现

發(fā)布時(shí)間:2024/4/19 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv求两张图像光流_光流(optical flow)和openCV中实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載請(qǐng)注明出處!

光流(optical flow)和openCV中實(shí)現(xiàn)

光流的概念:

是Gibson在1950年首先提出來(lái)的。

它是空間運(yùn)動(dòng)物體在觀察成像平面上的像素運(yùn)動(dòng)的瞬時(shí)速度。是利用圖像序列中像素在時(shí)間域上的變化以及相鄰幀之間的相關(guān)性來(lái)找到上一幀跟當(dāng)前幀之間存在的相應(yīng)關(guān)系,從而計(jì)算出相鄰幀之間物體的運(yùn)動(dòng)信息的一種方法。

一般而言。光流是因?yàn)閳?chǎng)景中前景目標(biāo)本身的移動(dòng)、相機(jī)的運(yùn)動(dòng),或者兩者的共同運(yùn)動(dòng)所產(chǎn)生的。

當(dāng)人的眼睛觀察運(yùn)動(dòng)物體時(shí),物體的景象在人眼的視網(wǎng)膜上形成一系列連續(xù)變化的圖像。這一系列連續(xù)變化的信息不斷“流過(guò)”視網(wǎng)膜(即圖像平面)。好像一種光的“流”,故稱之為光流(optical flow)。光流表達(dá)了圖像的變化,因?yàn)樗四繕?biāo)運(yùn)動(dòng)的信息。因此可被觀察者用來(lái)確定目標(biāo)的運(yùn)動(dòng)情況。

看以下的圖。它展示了一個(gè)小球在5個(gè)連續(xù)的幀中的運(yùn)動(dòng)。箭頭上的數(shù)字代表不同的幀。那個(gè)紅色小球的運(yùn)動(dòng)構(gòu)成了光流。

操作:

給你一個(gè)圖上的一系列點(diǎn),在另外一張圖上找到與前面一些列點(diǎn)同樣的點(diǎn)。

或者給你圖I1上的點(diǎn)[ux, uy]T。找到I2上的點(diǎn)[ux

+ δx, uy + δy]T。最小化ε:

上面增加Wx表示一塊區(qū)域,一般跟蹤一個(gè)區(qū)域的點(diǎn)。

在圖形學(xué)應(yīng)用中。在多張圖上跟蹤點(diǎn)(特征)是一項(xiàng)主要的操作:在一張圖上找到一個(gè)對(duì)象,觀察對(duì)象怎樣移動(dòng)。

基于特征點(diǎn)的跟蹤算法大致能夠分為兩個(gè)步驟:

1)探測(cè)當(dāng)前幀的特征點(diǎn);

2)通過(guò)當(dāng)前幀和下一幀灰度比較,預(yù)計(jì)當(dāng)前幀特征點(diǎn)在下一幀的位置;

3)過(guò)濾位置不變的特征點(diǎn),余下的點(diǎn)就是目標(biāo)了。

特征點(diǎn)能夠是Harris角點(diǎn),也能夠是邊緣點(diǎn)等等。

考慮一個(gè)像素

在第一幀的光強(qiáng)度(這里添加了一個(gè)維度時(shí)間。前面的時(shí)候我們僅僅是處理圖像。所以沒(méi)有必要時(shí)間。如今須要添加這個(gè)維度)。它移動(dòng)了?

的距離到一下幀。用了

時(shí)間。

由于像素點(diǎn)是一樣的。光強(qiáng)度也沒(méi)有發(fā)生變化(事實(shí)上這個(gè)光強(qiáng)度沒(méi)有改變是非常多光流算法的基本如果)。。所以我們能夠說(shuō):

然后通過(guò)泰勒級(jí)數(shù)近似展開有:

所以:

上面的等式叫做光流等式,偏導(dǎo)數(shù)能夠求出來(lái)。但是 u和v是未知的,所以無(wú)法解決上的等式。但是有非常多方法能夠解決問(wèn)題,當(dāng)中一個(gè)叫做Lucas-Kanade方法。

Lucas-Kanade:

有這么一個(gè)假定,全部的相鄰像素有相似的行動(dòng),Lucas-Kanade方法使用3*3的一塊區(qū)域,它假定這9個(gè)點(diǎn)有同樣的行動(dòng),所以如今的問(wèn)題變?yōu)橛?個(gè)等式,2個(gè)未知量,這個(gè)問(wèn)題當(dāng)然可以解決。一個(gè)好的解決方案是使用最小二乘法。

令n=9,于是便有了9個(gè)等式:

當(dāng)中q1,q2,…,代表像素點(diǎn),

是偏導(dǎo),上面的等式能夠?qū)懗梢韵碌男问?#xff1a;A

v = b,當(dāng)中:

然后,得到以下的:

終于算出來(lái)的兩個(gè)未知數(shù)的解是:

上面的解決小而連貫的運(yùn)動(dòng)。想想剛剛我們的如果是9個(gè)像素點(diǎn)速度一致。由于現(xiàn)實(shí)中大而連貫的運(yùn)動(dòng)是普遍存在的,我們須要大的窗體來(lái)捕獲運(yùn)動(dòng)。但是大窗體違背了運(yùn)動(dòng)連貫的如果。圖像金字塔能夠解決問(wèn)題。(圖像金字塔的內(nèi)容以后本人掌握很多其它的再補(bǔ)充。如今不敢亂發(fā)表)。

OpenCV中的實(shí)現(xiàn):

OpenCV提供了對(duì)上面介紹的方法的支持。函數(shù)名叫做:cv2.calcOpticalFlowPyrLK(),如今讓我們?cè)谝曨l中跟蹤一些點(diǎn)。

為了決定跟蹤哪些點(diǎn),使用cv2.goodFeaturesToTrack()。

我們得到第一幀。探測(cè)Shi-Tomasi角點(diǎn),然后我們使用?Lucas-Kanade光流法來(lái)跟綜這些點(diǎn)。

#include "opencv2/video/tracking.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/highgui/highgui.hpp"

#include

#include

using namespace cv;

using namespace std;

static void help()

{

// print a welcome message, and the OpenCV version

cout << "\nThis is ademo of Lukas-Kanade optical flow lkdemo(),\n"

"Using OpenCVversion "<< CV_VERSION << endl;

cout << "\nIt usescamera by default, but you can provide a path to video as an argument.\n";

cout << "\nHot keys:\n"

"\tESC - quitthe program\n"

"\tr -auto-initialize tracking\n"

"\tc - deleteall the points\n"

"\tn - switch the\"night\" mode on/off\n"

"To add/removea feature point click it\n" << endl;

}

Point2f point;

bool addRemovePt = false;

static void onMouse(int event, int x, int y, int /*flags*/, void* /*param*/)

{

if (event == CV_EVENT_LBUTTONDOWN)

{

point = Point2f((float)x, (float)y);

addRemovePt = true;

}

}

int main(int argc, char** argv)

{

help();

VideoCapture cap;

TermCriteria termcrit(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03);

Size subPixWinSize(10, 10), winSize(31, 31);

const int MAX_COUNT = 500;

bool needToInit = false;

bool nightMode = false;

/*if (argc == 1 || (argc == 2 && strlen(argv[1])== 1 && isdigit(argv[1][0])))

cap.open(argc == 2 ? argv[1][0] - '0' :0);

else if (argc == 2)

cap.open(argv[1]);*/

cap.open("G:\\視頻分析入門練習(xí)\\視頻分析入門練習(xí) - 附件\\sample.avi");

if (!cap.isOpened())

{

cout << "Could notinitialize capturing...\n";

return 0;

}

namedWindow("LK", 1);

setMouseCallback("LK", onMouse, 0);

Mat gray, prevGray, image;

vector points[2];

for (;;)

{

Mat frame;

cap >> frame;

if (frame.empty())

break;

frame.copyTo(image);

cvtColor(image, gray, COLOR_BGR2GRAY);

if (nightMode)

image = Scalar::all(0);

if (needToInit)

{

// automaticinitialization

goodFeaturesToTrack(gray, points[1],100, 0.01, 10, Mat(), 3, 0, 0.04);

cornerSubPix(gray, points[1],subPixWinSize, Size(-1, -1), termcrit);

addRemovePt = false;

}

else if(!points[0].empty())

{

vector status;

vector err;

if (prevGray.empty())

gray.copyTo(prevGray);

calcOpticalFlowPyrLK(prevGray, gray,points[0], points[1], status, err, winSize,

3, termcrit, 0, 0.001);

size_t i, k;

for (i = k = 0; i

{

if (addRemovePt)

{

if (norm(point -points[1][i]) <= 5)

{

addRemovePt = false;

continue;

}

}

if (!status[i])

continue;

points[1][k++] = points[1][i];

circle(image, points[1][i], 3, Scalar(0, 255, 0), -1, 8);

}

points[1].resize(k);

}

if (addRemovePt&& points[1].size() < (size_t)MAX_COUNT)

{

vector tmp;

tmp.push_back(point);

cornerSubPix(gray, tmp, winSize,cvSize(-1, -1), termcrit);

points[1].push_back(tmp[0]);

addRemovePt = false;

}

needToInit = false;

imshow("LK", image);

char c = (char)waitKey(100);

if (c == 27)

break;

switch (c)

{

case 'r':

needToInit = true;

break;

case 'c':

points[0].clear();

points[1].clear();

break;

case 'n':

nightMode = !nightMode;

break;

}

std::swap(points[1], points[0]);

cv::swap(prevGray, gray);

}

return 0;

}

結(jié)果:任意取得一些特征點(diǎn)。特征點(diǎn)會(huì)隨著車的移動(dòng)而移動(dòng)

總結(jié)

以上是生活随笔為你收集整理的opencv求两张图像光流_光流(optical flow)和openCV中实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。