我認爲catmul-ROM花將是你的任務是不錯的選擇。
你可以找到執行此: http://www.codeproject.com/Articles/30838/Overhauser-Catmull-Rom-Splines-for-Camera-Animatio
回答AHF的評論(把它放在這裏通過的Qix建議):
此代碼草圖允許你編輯用鼠標花從使用的文件this link(附加到您的項目:overhauser.cpp overhauser.hpp和vec3.hpp):
鼠標左鍵添加/移動一個點,右鍵刪除。
代碼不是很困難,所以我做了1通道修改(爲了緊湊)。
我想你會接受這個想法。
#include <iostream>
#include <vector>
#include <stdio.h>
#include <functional>
#include <algorithm>
#include <numeric>
#include <cstddef>
#include "opencv2/opencv.hpp"
#include <iostream>
#include <fstream>
#include "overhauser.hpp"
using namespace std;
using namespace cv;
Mat result;
Mat Img;
vector<cv::Point2f> pts;
Mat curvesImg;
int selectedPt=-1;
CRSpline* spline = 0;
unsigned char LUT_RED[256];
// a case-insensitive comparison function:
bool mycomp (Point2f p1, Point2f p2)
{
return p1.x<p2.x;
}
float dist(Point2f p1,Point2f p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
int findNEarestPt(Point2f pt, float maxDist)
{
float minDist=FLT_MAX;
int ind=-1;
for(int i=0;i<pts.size();++i)
{
float d=dist(pt,pts[i]);
if(minDist>d)
{
ind=i;
minDist=d;
}
}
if(minDist>maxDist)
{
ind=-1;
}
return ind;
}
float F(float t,float x)
{
vec3 rv = spline->GetInterpolatedSplinePoint(t);
return x-rv.x;
}
float solveForX(float x)
{
float a=0,b=1.0,c,e=1e-5;
c=(a+b)/2;
while((fabs(b-a)>e) && (F(c,x)!=0))
{
if (F(a,x)*F(c,x)<0)
{
b=c;
}
else
{
a=c;
}
c=(a+b)/2;
}
return c;
}
int ind=-1;
void mouseHandler(int event, int x, int y, int flags, void* param)
{
Point2f m;
m.x=x;
m.y=y;
curvesImg=Scalar(0,0,0);
switch (event)
{
case cv::EVENT_RBUTTONDOWN:
ind=findNEarestPt(m,5);
if (ind==-1)
{
}else
{
pts.erase(pts.begin()+ind);
ind=-1;
}
break;
case cv::EVENT_LBUTTONDOWN:
ind=findNEarestPt(m,5);
if (ind==-1)
{
pts.push_back(m);
selectedPt=pts.size()-1;
}else
{
selectedPt=ind;
}
break;
case cv::EVENT_MOUSEMOVE:
if(ind!=-1)
{
pts[selectedPt].x=m.x;
pts[selectedPt].y=m.y;
}
break;
case cv::EVENT_LBUTTONUP:
ind=-1;
break;
}
std::sort(pts.begin(),pts.end(),mycomp);
if(pts.size()>0)
{
pts[pts.size()-1].x=curvesImg.cols;
pts[0].x=0;
}
for(int i=0;i<pts.size();++i)
{
circle(curvesImg,pts[i],5,Scalar(0,255,255),-1,CV_AA);
}
if (spline) {delete spline;}
spline = new CRSpline();
for (int i=0;i<pts.size();++i)
{
vec3 v(pts[i].x,pts[i].y,0);
spline->AddSplinePoint(v);
}
vec3 rv_last(0,0,0);
if(pts.size()>2)
{
for(int i=0;i<256;++i)
{
float t=solveForX(i);
vec3 rv = spline->GetInterpolatedSplinePoint(t);
unsigned char I=(unsigned char)(rv.y);
LUT_RED[i]=255-I;
if(i>1)
{
line(curvesImg,Point(rv.x,rv.y),Point(rv_last.x,rv_last.y),Scalar(0,0,255),1);
}
rv_last=rv;
}
}
line(curvesImg,Point(0,m.y),Point(curvesImg.cols,m.y),Scalar(0,255,0),1);
line(curvesImg,Point(m.x,0),Point(m.x,curvesImg.rows),Scalar(0,255,0),1);
imshow("Result",curvesImg);
vector<Mat> ch;
cv::split(Img,ch);
LUT(ch[2],Mat(256,1,CV_8UC1,LUT_RED),ch[2]);
cv::merge(ch,result);
imshow("Transformed",result);
}
// ---------------------------------
//
// ---------------------------------
//==============================================================================
int main(int argc, char** argv)
{
for (int i=0;i<256;++i)
{
LUT_RED[i]=i;
}
namedWindow("Image",cv::WINDOW_NORMAL);
namedWindow("Result");
namedWindow("Transformed");
Img=imread("D:\\ImagesForTest\\lena.jpg",1);
imshow("Image",Img);
curvesImg=Mat::zeros(256,256,CV_8UC3);
setMouseCallback("Result", mouseHandler, NULL);
waitKey(0);
getchar();
}
參見[approxPolyDP(http://docs.opencv.org/doc/tutorials/imgproc/shapedescriptors/bounding_rects_circles/bounding_rects_circles.html)可能會有所幫助。 – Haris
「平滑」意味着(a)對產生這些點的過程有一些假設 - 您是否有物理模型?以及與它們相關的「噪音」/「誤差」(它們與假設模型的偏差)? (b)在曲線中考慮一些應用程序 - 生成漂亮的圖片以查看是一個應用程序,但也許您有一些特定的需求來從樣本和模型中進行插值/外插? 您需要回答(a)和(b)以取得進展。 –
@哈里斯我嘗試使用findContours和approxPolyDP到我的代碼。但是,由於訪問衝突錯誤,我無法工作。 – Eagle