lk演算法
『壹』 cvcalcopticalflowpyrlk在opencv哪個庫裡面
void cvCalcOpticalFlowLK( const CvArr* prev, const CvArr* curr, CvSize win_size, CvArr* velx, CvArr* vely );
void cvCalcOpticalFlowPyrLK( const CvArr* prev, const CvArr* curr, CvArr* prev_pyr, CvArr* curr_pyr,
const CvPoint2D32f* prev_features, CvPoint2D32f* curr_features,
int count, CvSize win_size, int level, char* status,
float* track_error, CvTermCriteria criteria, int flags );
對比這兩個函數,前者cvCalcOpticalFlowLK(參數中包含光流速度(稠密的光流場) CvArr* velx, CvArr* vely ,然而
cvCalcOpticalFlowPyrLK的參數中確實兩個特徵點數組CvPoint2D32f* prev_features, CvPoint2D32f* curr_features。
對於cvCalcOpticalFlowLK函數的原理,《learning opencv》中介紹的比較清楚,也可以參考http://www.360doc.com/content/11/0210/17/5367933_91913320.shtml這篇博文。
cvCalcOpticalFlowPyrLK函數給人的感覺更像塊匹配,用歸一化相關求出特徵點在下一幀的位移,這好像和光流機Lk演算法關系不大。查閱了相關文獻,思考 cvCalcOpticalFlowPyrLK的原理,確實和塊匹配類似,只不過沒有空歸一化相關的方法,用的偏導的方法。由偏導的方法也就和LK演算法及光流掛上了鉤。
金字塔LK演算法(cvCalcOpticalFlowPyrLK)的兩個特點,一、金字塔原理;二、偏導方法求解位移。
『貳』 實現改進後的順序查找
你看一下對你有沒有幫助啊! // search.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "LinkTable.h"
#define MAX_KEY 500
//------------------------------數組實現部分----------------------------------
/**//*
無序數組順序查找演算法函數nsq_Order_Search<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: nsq_Order_Search = -1
否則: nsq_Order_Search = key數組下標
*/
int nsq_Order_Search(int array[],int n,int key)
...{
int i;
array[n] = key;
/**//*for循環後面的分號必不可少*/
for(i=0;key!=array[i];i++);
return(i<n?i:-1);
}
/**//*
有序數組順序查找演算法函數sq_Order_Search<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Order_Search = -1
否則: sq_Order_Search = key數組下標
*/
int sq_Order_Search(int array[],int n,int key)
...{
int i;
array[n] = MAX_KEY;
/**//*for循環後面的分號必不可少*/
for(i=0;key>array[i];i++);
if(i<n && array[i] == key)
return(i);
else
return(-1);
}
/**//*
有序數組二分查找演算法函數sq_Dichotomy_Search0<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Dichotomy_Search0 = -1
否則: sq_Dichotomy_Search0 = key數組下標
*/
int sq_Dichotomy_Search0(int array[],int n,int key)
...{
int low,high,mid;
low = 0;
high = n - 1;
while(low<=high)
...{
mid = (high+low)/2;
if(array[mid] == key)
return(mid);
/**//*key>array[mid] 表明要求查找的值在[mid+1,high]*/
/**//*否則,在[low,mid-1]*/
if(key > array[mid])
low = mid + 1;
else
high = mid - 1;
}
return(-1);
}
/**//*
有序數組插值查找演算法函數sq_Dichotomy_Search1<用數組實現>
(插值查找演算法是二分查找演算法的改進)
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Dichotomy_Search1 = -1
否則: sq_Dichotomy_Search1 = key數組下標
*/
int sq_Dichotomy_Search1(int array[],int n,int key)
...{
int low,high, //二分數組的上,下標
pos; //查找碼的大致(估算)位置
low = 0;
high = n-1;
while(low <= high)
...{
pos = (key-array[low])/(array[high]-array[low])*(high-low)+low;
/**//*找到關鍵值,中途退出*/
if(key == array[pos])
return(pos);
if(key > array[pos])
low = pos + 1;
else
high = pos - 1;
}
/**//*沒有找到,返回-1*/
return(-1);
}
//------------------------------數組實現部分----------------------------------
//------------------------------鏈表實現部分----------------------------------
/**//*
無序鏈表順序查找演算法函數nlk_Order_Serach<用鏈表實現>
[查找思想:遍歷鏈表的所有節點]
參數描述:
Node *head :被查找鏈表的首指針
int key :被查找的關鍵值
返回值:
如果沒有找到: nlk_Order_Serach = NULL
否則: nlk_Order_Serach = 鍵值為key的節點的指針
*/
Node *nlk_Order_Serach(Node *head,int key)
...{
for(;head!=NULL && head->data != key;head = head->link);
return(head);
}
/**//*
有序鏈表順序查找演算法函數lk_Order_Serach<用鏈表實現>
[查找思想:依次遍歷鏈表的節點,發現節點不在key的范圍時提前結束查找]
參數描述:
Node *head :被查找鏈表的首指針
int key :被查找的關鍵值
返回值:
如果沒有找到: lk_Order_Serach = NULL
否則: lk_Order_Serach = 鍵值為key的節點的指針
*/
Node *lk_Order_Search(Node *head,int key)
...{
for(;head!=NULL && head->data < key;head=head->link);
/**//*當遍歷指針為NULL或沒有找到鍵值為key的節點,返回NULL(表明沒有找到)*/
/**//*否則,返回head(表明已經找到)*/
return(head==NULL || head->data != key ? NULL : head);
}
/**//*
有序鏈表動態查找演算法函數lk_Dynamic_Search<用鏈表實現>
[查找思想:依次遍歷鏈表的節點,發現節點不在key的范圍時提前結束查找]
參數描述:
Node *head: 被查找鏈表的首指針
Node **p; 鍵值為key的節點的前驅指針(回傳參數)
Node **q: 鍵值為key的節點指針(回傳參數)
int key : 被查找的關鍵值
注意:
當 *p == NULL 且 *q != NULL,鏈表的首節點鍵值為key
當 *p != NULL 且 *q != NULL,鏈表的中間(非首,尾)節點鍵值為key
當 *p != NULL 且 *q == NULL,鏈表的尾節點鍵值為key
當 *p == NULL 且 *q == NULL,鏈表是空鏈表
*/
void lk_Dynamic_Search(Node *head,Node **p,Node **q,int key)
...{
Node *pre,*cur;
pre = NULL;
cur = head;
for(;cur != NULL && cur->data < key;pre = cur,cur = cur->link)
*p = pre;
*q = cur;
}
/**//*
有序鏈表動態插入演算法函數lk_Dynamic_Insert<用鏈表實現>
參數描述:
Node *head: 被插入鏈表的首指針
int key : 被插入的關鍵值
返回值:
lk_Dynamic_Search = 插入鍵值為key的節點後的鏈表首指針
*/
Node *lk_Dynamic_Insert(Node *head,int key)
...{
Node
*x, //插入節點的前驅節點
*y, //插入節點的後續節點
*p; //插入的節點
p = (Node *)malloc(sizeof(Node));
p->data = key;
p->link = NULL;
lk_Dynamic_Search(head,&x,&y,key);
if(x==NULL)
...{
p->link = x;
head = p;
}
else
...{
p->link = x->link;
x->link = p;
}
ListLinkTable(head,"插入節點");
return(head);
}
/**//*
有序鏈表動態刪除演算法函數lk_Dynamic_Delete<用鏈表實現>
參數描述:
Node *head: 被刪除鏈表的首指針
int key : 被刪除的關鍵值
返回值:
lk_Dynamic_Delete = 刪除鍵值為key的節點後的鏈表首指針
*/
Node *lk_Dynamic_Delete(Node *head,int key)
...{
Node *x, //刪除節點的前驅節點
*y; //刪除的節點
lk_Dynamic_Search(head,&x,&y,key);
if(x==NULL)
/**//*因為x=NLLL時,y指向首指針*/
head = y->link;
else
x->link = y->link;
free(y);
ListLinkTable(head,"刪除節點");
return(head);
}
//------------------------------鏈表實現部分----------------------------------
int main(int argc, char* argv[])
...{
Node *head;
//Node *p,*x,*y;
int KEY;
int count,i;
//int result;
KEY = 11;
//PrintArrayValue(TestArray2,DEFAULT_ARRAY_SIZE,"原始");
//result = sq_Dichotomy_Search1(TestArray2,DEFAULT_ARRAY_SIZE,KEY);
//printf("查找結果是:數組[%d] = %d ",result,TestArray2[result]);
head = CreateLinkTable(DEFAULT_ARRAY_SIZE,TestArray2);
ListLinkTable(head,"原始");
/**//*
p = lk_Order_Search(head,KEY);
if(p==NULL)
printf(" 查找結果是:指定鏈表中沒有[數據域 = %d]的節點! ",KEY);
else
printf(" 查找結果是:節點.Data = %d 節點.Link = %d 節點.Addr = %d ",p->data,p->link,p);
*/
printf("輸入插入節點的個數: ");
scanf("%d",&count);
for(i=0;i<count;i++)
...{
printf("輸入插入節點的數據域: ");
scanf("%d",&KEY);
lk_Dynamic_Insert(head,KEY);
}
do
...{
printf("輸入刪除節點的數據域: ");
scanf("%d",&KEY);
lk_Dynamic_Delete(head,KEY);
}while(head!=NULL);
printf(" 應用程序正在運行...... ");
return 0;
}
『叄』 數據挖掘中的apriori演算法的具體步驟是什麼
演算法:Apriori
輸入:D - 事務資料庫;min_sup - 最小支持度計數閾值
輸出:L - D中的頻繁項集
方法:
L1=find_frequent_1-itemsets(D); // 找出所有頻繁1項集
For(k=2;Lk-1!=null;k++){
Ck=apriori_gen(Lk-1); // 產生候選,並剪枝
For each 事務t in D{ // 掃描D進行候選計數
Ct =subset(Ck,t); // 得到t的子集
For each 候選c 屬於 Ct
c.count++;
}
Lk={c屬於Ck | c.count>=min_sup}
}
Return L=所有的頻繁集;
Procere apriori_gen(Lk-1:frequent(k-1)-itemsets)
For each項集l1屬於Lk-1
For each項集 l2屬於Lk-1
If((l1[1]=l2[1])&&( l1[2]=l2[2])&&……..
&& (l1[k-2]=l2[k-2])&&(l1[k-1]<l2[k-1])) then{
c=l1連接l2 //連接步:產生候選
if has_infrequent_subset(c,Lk-1) then
delete c; //剪枝步:刪除非頻繁候選
else add c to Ck;
}
Return Ck;
Procere has_infrequent_sub(c:candidate k-itemset; Lk-1:frequent(k-1)-itemsets)
For each(k-1)-subset s of c
If s不屬於Lk-1 then
Return true;
Return false;
『肆』 急求演算法!!
暈倒,全部分數只有20分,看在你的誠意,給你寫第一個吧。
第一題如果直接舉證相乘是三次的,比較是二次的,綜合起來是三次,不滿足你的要求。
但是我們換一種思路,利用隨機演算法,一個1*n的矩陣乘以一個n*n的矩陣是一個1*n的矩陣,乘法次數是二次的,因此如果把等式兩邊同時乘以一個1*n的矩陣兩邊還是相等的,但是復雜度只有n*n。
那個1*n矩陣怎麼得到呢?隨機就可以,兩次左右的隨機就能保證正確性了,下面是代碼,格式是先讀入一個n,然後讀入兩個n*n個矩陣(就是2*n*n個整數),如果AB=C輸出YES,否則輸出NO,採用了兩次隨機判定,判誤率很高,但是沒算過,隨機種子是我隨手打的,取得好一點可能判誤率更高。
#include<stdio.h>
#include<stdlib.h>
int i,j,n,a[500][500],b[500][500],c[500][500];
bool can;
void oper()
{
int i,j,temp[500],mid[500],s,tempb[500];
for (i=0;i<n;i++) mid[i]=rand()%100+1;
for (i=0;i<n;i++)
{
temp[i]=0;
for (j=0;j<n;j++)
temp[i]+=mid[j]*a[j][i];
}
for (i=0;i<n;i++)
{
tempb[i]=0;
for (j=0;j<n;j++)
tempb[i]+=temp[j]*b[j][i];
}
for (i=0;i<n;i++)
{
s=0;
for (j=0;j<n;j++)
s+=mid[j]*c[j][i];
if (s!=tempb[i])
{
can=false;
return;
}
}
}
int main()
{
srand(756);
scanf("%d",&n);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
scanf("%d",&a[i][j]);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
scanf("%d",&b[i][j]);
for (i=0;i<n;i++)
for (j=0;j<n;j++)
scanf("%d",&c[i][j]);
can=true;
for (i=0;i<2;i++)
{
oper();
if (!can) break;
}
if (can) printf("YES\n");
else printf("NO\n");
return 0;
}
『伍』 利用Apriori演算法產生頻繁項集,(min sup=0.6),給出具體計算過程
Apriori演算法是一種發現頻繁項集的基本演算法。演算法使用頻繁項集性質的先驗知識。Apriori演算法使用一種稱為逐層搜索的迭代方法,其中K項集用於探索(k+1)項集。首先,通過掃描資料庫,累計每個項的計數,並收集滿足最小支持度的項,找出頻繁1項集的集合。該集合記為L1.然後,使用L1找出頻繁2項集的集合L2,使用L2找到L3,如此下去,直到不能再找到頻繁k項集。Apriori演算法的主要步驟如下:(1)掃描事務資料庫中的每個事務,產生候選1.項集的集合Cl;(2)根據最小支持度min_sup,由候選l-項集的集合Cl產生頻繁1一項集的集合Ll;(3)對k=l;(4)由Lk執行連接和剪枝操作,產生候選(k+1).項集的集合Ck+l-(5)根據最小支持度min_sup,由候選(k+1)一項集的集合Ck+l產生頻繁(k+1)-項集的集合Lk+1.(6)若L?≠①,則k.k+1,跳往步驟(4);否則,跳往步驟(7);(7)根據最小置信度min_conf,由頻繁項集產生強關聯規則,結束。
『陸』 編寫順序查找演算法的程序
查找演算法集:順序查找、二分查找、插值查找、動態查找(數組實現、鏈表實現)
// search.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "LinkTable.h"
#define MAX_KEY 500
//------------------------------數組實現部分----------------------------------
/**//*
無序數組順序查找演算法函數nsq_Order_Search<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: nsq_Order_Search = -1
否則: nsq_Order_Search = key數組下標
*/
int nsq_Order_Search(int array[],int n,int key)
...{
int i;
array[n] = key;
/**//*for循環後面的分號必不可少*/
for(i=0;key!=array[i];i++);
return(i<n?i:-1);
}
/**//*
有序數組順序查找演算法函數sq_Order_Search<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Order_Search = -1
否則: sq_Order_Search = key數組下標
*/
int sq_Order_Search(int array[],int n,int key)
...{
int i;
array[n] = MAX_KEY;
/**//*for循環後面的分號必不可少*/
for(i=0;key>array[i];i++);
if(i<n && array[i] == key)
return(i);
else
return(-1);
}
/**//*
有序數組二分查找演算法函數sq_Dichotomy_Search0<用數組實現>
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Dichotomy_Search0 = -1
否則: sq_Dichotomy_Search0 = key數組下標
*/
int sq_Dichotomy_Search0(int array[],int n,int key)
...{
int low,high,mid;
low = 0;
high = n - 1;
while(low<=high)
...{
mid = (high+low)/2;
if(array[mid] == key)
return(mid);
/**//*key>array[mid] 表明要求查找的值在[mid+1,high]*/
/**//*否則,在[low,mid-1]*/
if(key > array[mid])
low = mid + 1;
else
high = mid - 1;
}
return(-1);
}
/**//*
有序數組插值查找演算法函數sq_Dichotomy_Search1<用數組實現>
(插值查找演算法是二分查找演算法的改進)
參數描述:
int array[] :被查找數組
int n :被查找數組元素個數
int key :被查找的關鍵值
返回值:
如果沒有找到: sq_Dichotomy_Search1 = -1
否則: sq_Dichotomy_Search1 = key數組下標
*/
int sq_Dichotomy_Search1(int array[],int n,int key)
...{
int low,high, //二分數組的上,下標
pos; //查找碼的大致(估算)位置
low = 0;
high = n-1;
while(low <= high)
...{
pos = (key-array[low])/(array[high]-array[low])*(high-low)+low;
/**//*找到關鍵值,中途退出*/
if(key == array[pos])
return(pos);
if(key > array[pos])
low = pos + 1;
else
high = pos - 1;
}
/**//*沒有找到,返回-1*/
return(-1);
}
//------------------------------數組實現部分----------------------------------
//------------------------------鏈表實現部分----------------------------------
/**//*
無序鏈表順序查找演算法函數nlk_Order_Serach<用鏈表實現>
[查找思想:遍歷鏈表的所有節點]
參數描述:
Node *head :被查找鏈表的首指針
int key :被查找的關鍵值
返回值:
如果沒有找到: nlk_Order_Serach = NULL
否則: nlk_Order_Serach = 鍵值為key的節點的指針
*/
Node *nlk_Order_Serach(Node *head,int key)
...{
for(;head!=NULL && head->data != key;head = head->link);
return(head);
}
/**//*
有序鏈表順序查找演算法函數lk_Order_Serach<用鏈表實現>
[查找思想:依次遍歷鏈表的節點,發現節點不在key的范圍時提前結束查找]
參數描述:
Node *head :被查找鏈表的首指針
int key :被查找的關鍵值
返回值:
如果沒有找到: lk_Order_Serach = NULL
否則: lk_Order_Serach = 鍵值為key的節點的指針
*/
Node *lk_Order_Search(Node *head,int key)
...{
for(;head!=NULL && head->data < key;head=head->link);
/**//*當遍歷指針為NULL或沒有找到鍵值為key的節點,返回NULL(表明沒有找到)*/
/**//*否則,返回head(表明已經找到)*/
return(head==NULL || head->data != key ? NULL : head);
}
/**//*
有序鏈表動態查找演算法函數lk_Dynamic_Search<用鏈表實現>
[查找思想:依次遍歷鏈表的節點,發現節點不在key的范圍時提前結束查找]
參數描述:
Node *head: 被查找鏈表的首指針
Node **p; 鍵值為key的節點的前驅指針(回傳參數)
Node **q: 鍵值為key的節點指針(回傳參數)
int key : 被查找的關鍵值
注意:
當 *p == NULL 且 *q != NULL,鏈表的首節點鍵值為key
當 *p != NULL 且 *q != NULL,鏈表的中間(非首,尾)節點鍵值為key
當 *p != NULL 且 *q == NULL,鏈表的尾節點鍵值為key
當 *p == NULL 且 *q == NULL,鏈表是空鏈表
*/
void lk_Dynamic_Search(Node *head,Node **p,Node **q,int key)
...{
Node *pre,*cur;
pre = NULL;
cur = head;
for(;cur != NULL && cur->data < key;pre = cur,cur = cur->link)
*p = pre;
*q = cur;
}
/**//*
有序鏈表動態插入演算法函數lk_Dynamic_Insert<用鏈表實現>
參數描述:
Node *head: 被插入鏈表的首指針
int key : 被插入的關鍵值
返回值:
lk_Dynamic_Search = 插入鍵值為key的節點後的鏈表首指針
*/
Node *lk_Dynamic_Insert(Node *head,int key)
...{
Node
*x, //插入節點的前驅節點
*y, //插入節點的後續節點
*p; //插入的節點
p = (Node *)malloc(sizeof(Node));
p->data = key;
p->link = NULL;
lk_Dynamic_Search(head,&x,&y,key);
if(x==NULL)
...{
p->link = x;
head = p;
}
else
...{
p->link = x->link;
x->link = p;
}
ListLinkTable(head,"插入節點");
return(head);
}
/**//*
有序鏈表動態刪除演算法函數lk_Dynamic_Delete<用鏈表實現>
參數描述:
Node *head: 被刪除鏈表的首指針
int key : 被刪除的關鍵值
返回值:
lk_Dynamic_Delete = 刪除鍵值為key的節點後的鏈表首指針
*/
Node *lk_Dynamic_Delete(Node *head,int key)
...{
Node *x, //刪除節點的前驅節點
*y; //刪除的節點
lk_Dynamic_Search(head,&x,&y,key);
if(x==NULL)
/**//*因為x=NLLL時,y指向首指針*/
head = y->link;
else
x->link = y->link;
free(y);
ListLinkTable(head,"刪除節點");
return(head);
}
//------------------------------鏈表實現部分----------------------------------
int main(int argc, char* argv[])
...{
Node *head;
//Node *p,*x,*y;
int KEY;
int count,i;
//int result;
KEY = 11;
//PrintArrayValue(TestArray2,DEFAULT_ARRAY_SIZE,"原始");
//result = sq_Dichotomy_Search1(TestArray2,DEFAULT_ARRAY_SIZE,KEY);
//printf("查找結果是:數組[%d] = %d ",result,TestArray2[result]);
head = CreateLinkTable(DEFAULT_ARRAY_SIZE,TestArray2);
ListLinkTable(head,"原始");
/**//*
p = lk_Order_Search(head,KEY);
if(p==NULL)
printf(" 查找結果是:指定鏈表中沒有[數據域 = %d]的節點! ",KEY);
else
printf(" 查找結果是:節點.Data = %d 節點.Link = %d 節點.Addr = %d ",p->data,p->link,p);
*/
printf("輸入插入節點的個數: ");
scanf("%d",&count);
for(i=0;i<count;i++)
...{
printf("輸入插入節點的數據域: ");
scanf("%d",&KEY);
lk_Dynamic_Insert(head,KEY);
}
do
...{
printf("輸入刪除節點的數據域: ");
scanf("%d",&KEY);
lk_Dynamic_Delete(head,KEY);
}while(head!=NULL);
printf(" 應用程序正在運行...... ");
return 0;
}
『柒』 如何使用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");
}
『捌』 編寫一個演算法來交換單鏈表中指針P所指結點與其後繼結點
void swape(linklist &head,linklist &p)
{
linlklist q=head,r=p->next;
while(q->next!=p)q=q->next;
q->next=r;
p->next=r->next;
r->next=p;
}
『玖』 設計一個計算表頭指針為LK_h的單鏈式表長度(即結點個數)的演算法
long getLength(Node* h) //Node 為節點類型 { Node *p=h->next; long len=0; while (p!=NULL) { p=p->next; len++; } return len; }
『拾』 馬爾可夫鏈演算法
// Markov.bss
// 用koodoo語言實現馬爾可夫鏈演算法
// 這也是對文件操作、散列數組的演示
// 馬爾可夫鏈演算法具體的說明請參閱《程序設計實踐》
// (Brian W.Kernighan & Rob Pike著, 裘宗燕譯, 機械工業出版社2000版)
// 輸入文件: "month.txt" -- 《人月神話》的一段話
// 輸出文件: "out1.txt"
// 深圳市藍星際公司 2004
// [email protected]
// markov chain algorithm for 2-word prefixes
const MAXGEN = 10000;
CR = 0;
Chr(13, CR);
NONWORD = CR;
c2 = 0;
Chr(10, c2);
CR = CR + c2;
w1 = NONWORD;
w2 = NONWORD;
LK = "";
Chr(15, LK);
inFile = "month.txt";
outFile = "out1.txt";
// 只讀方式打開輸入文件
hd = -1;
FileOpen(inFile, "rt", hd);
if( hd<0 )
{
return(0);
}
statetab = 0;
nsuffix = 0;
s = "";
while(true)
{
FileReadLine(hd, s); // 讀一行
if( s=="" )
{
// 到了文件結束
break;
}
m = 0;
AnlyStr(s, " ", m); // 將一行的內容分解為單詞, 存放在數組m
num = _retVal; // 單詞數
for(i=0; i<num; i++)
{
k1 = w1 + LK + w2; // 將w1, w2連接起來模擬2維數組
v = nsuffix[k1];
t = 0;
Type(v, t);
if( t==0 ) // 表示該下標首次使用
{
nsuffix[k1] = 0;
}
nsuffix[k1] = 1 + nsuffix[k1];
k2 = k1 + LK + nsuffix[k1]; // 模擬3維數組
statetab[k2] = m[i];
w1 = w2;
w2 = m[i];
}
}
FileClose(hd);
// 創建輸出文件
hd = -1;
FileOpen(outFile, "w+t", hd);
if( hd<0 )
{
return(0);
}
k1 = w1 + LK + w2;
v = nsuffix[k1];
t = 0;
Type(v, t);
if( t==0 )
{
nsuffix[k1] = 0;
}
nsuffix[k1] = nsuffix[k1] + 1;
k2 = k1 + LK + nsuffix[k1];
statetab[k2] = NONWORD;
w1 = NONWORD;
w2 = NONWORD;
for(i=0; i<MAXGEN; i++)
{
r = 0;
Rand(r);
k1 = w1 + LK + w2;
r = r % nsuffix[k1] + 1;
k2 = k1 + LK + r;
p = statetab[k2];
if( p== NONWORD )
{
break;
}
FileWrite(hd, p);
FileWrite(hd, " ");
w1 = w2;
w2 = p;
}
FileCloseAll();
return(0);