一个图片长方形的,我们正面看过去的时候(拍照拍下来),是一个长方形,但是我们侧面看过去的时候还是拍照拍下来,图片就看上去就变化了,我需要获得从侧面看过去的时候的图片效果图,哪位知道或有现成的算法提供一下,非常感谢,高分相送,分不够可以再说1千都可以,很急

解决方案 »

  1.   

    //我写了个简单的3DCanvas类,你可以看看我的应用.
    unit QQCanvas3D;interface
    uses Windows,SysUtils,Graphics;
    const
      SEEFAR=5000;//眼睛可看到的最远距离type
      T3DPoint=record
        x,y,z:Integer;
      end;
      T2DPoint=record
        x,y:Integer;
      end;
      TCanvas3D=class
      private
        FViewWidth: Integer;
        FViewHeight: Integer;
        FOrigin: T3DPoint;
        FFCanvas2D: TCanvas;
        procedure SetViewHeight(const Value: Integer);
        procedure SetViewWidth(const Value: Integer);
        procedure SetFCanvas2D(const Value: TCanvas);
        function GetPixels(x, y, z: Integer): TColor;
        procedure SetPixels(x, y, z: Integer; const Value: TColor);
        function GetBrush: TBrush;
        function GetPen: TPen;
        procedure SetBrush(const Value: TBrush);
        procedure SetPen(const Value: TPen);
        procedure SetOrigin(const Value: T3DPoint);
      protected
        function Point3DTo2D(const Point:T3DPoint):T2DPoint;overload;
        function Point3DTo2D(x,y,z:Integer):T2DPoint;overload;
      public
        constructor Create(Canvas:TCanvas);
        property FCanvas2D:TCanvas read FFCanvas2D write SetFCanvas2D;    procedure MoveTo(x,y,z:Integer);
        procedure LineTo(x,y,z:Integer);
        procedure Arc(x,y,z,r:Integer;StartRadian,EndRadian:Double);
        procedure Sphere(x,y,z,r:Integer;hs:Integer=100;vs:Integer=100);
        property Pixels[x,y,z:Integer]:TColor read GetPixels write SetPixels;
        property Pen:TPen read GetPen write SetPen;
        property Brush:TBrush read GetBrush write SetBrush;
        property Origin:T3DPoint read FOrigin write SetOrigin;
        property ViewWidth:Integer read FViewWidth write SetViewWidth;
        property ViewHeight:Integer read FViewHeight write SetViewHeight;
      end;implementation
    const
      RadianCount=7200;
      PI=3.1415926;
      PI2=2*PI;var
      FSinArray:array[0..RadianCount] of Double;
      FCosArray:array[0..RadianCount] of Double;
      FRadianStep:Double;{ TCanvas3D }procedure TCanvas3D.Arc(x, y, z, r: Integer; StartRadian, EndRadian: Double);
    var
      bt,et,tx,ty:Integer;
      tRadian:Double;begin
      if StartRadian>EndRadian then
      begin
        tRadian:=StartRadian;
        StartRadian:=EndRadian;
        EndRadian:=tRadian;
      end;
      if EndRadian-StartRadian>PI2 then EndRadian:=StartRadian+PI2;
      bt:=Round(StartRadian/FRadianStep);
      et:=Round(EndRadian/FRadianStep);
      tx:=Round(FCosArray[bt]*r+x);
      ty:=Round(FSinArray[bt]*r+y);
      with Point3DTo2D(tx,ty,z) do
      begin
        FCanvas2D.MoveTo(x,y);
      end;
      inc(bt);
      while bt<et do
      begin
        tx:=Round(FCosArray[bt]*r+x);
        ty:=Round(FSinArray[bt]*r+y);
        with Point3DTo2D(tx,ty,z) do
        begin
          FCanvas2D.LineTo(x,y);
        end;
        inc(bt);
      end;
    end;constructor TCanvas3D.Create(Canvas:TCanvas);
    begin
      FCanvas2D:=Canvas;
      FViewWidth:=400;
      FViewHeight:=300;
      FOrigin.X:=0;
      FOrigin.Y:=0;
      FOrigin.Z:=0;
    end;
    function TCanvas3D.GetBrush: TBrush;
    begin
      Result:=FCanvas2D.Brush;
    end;function TCanvas3D.GetPen: TPen;
    begin
      Result:=FCanvas2D.Pen;
    end;function TCanvas3D.GetPixels(x, y, z: Integer): TColor;
    begin
      with Point3DTo2D(x,y,z) do
      begin
        Result:=FCanvas2D.Pixels[x,y];
      end;
    end;procedure TCanvas3D.LineTo(x, y, z: Integer);
    begin
      with Point3DTo2D(x,y,z) do
      begin
        FCanvas2D.LineTo(x,y);
      end;
    end;procedure TCanvas3D.MoveTo(x, y, z: Integer);
    begin
      with Point3DTo2D(x,y,z) do
      begin
        FCanvas2D.MoveTo(x,y);
      end;
    end;function TCanvas3D.Point3DTo2D(const Point: T3DPoint): T2DPoint;
    begin
      Result.x:=Round(Point.x*(1-(Point.z+Origin.z)/SEEFAR))+Origin.X;
      Result.y:=Round(Point.y*(1-(Point.z+Origin.z)/SEEFAR))+Origin.Y;
    end;function TCanvas3D.Point3DTo2D(x, y, z: Integer): T2DPoint;
    begin
      Result.x:=Round(x*(1-(z+Origin.z)/SEEFAR))+Origin.X;
      Result.y:=Round(y*(1-(z+Origin.z)/SEEFAR))+Origin.Y;
    end;
    procedure TCanvas3D.SetBrush(const Value: TBrush);
    begin
      FCanvas2D.Brush:=Value;
    end;procedure TCanvas3D.SetFCanvas2D(const Value: TCanvas);
    begin
      FFCanvas2D := Value;
    end;procedure TCanvas3D.SetOrigin(const Value: T3DPoint);
    begin
      FOrigin := Value;
    end;procedure TCanvas3D.SetPen(const Value: TPen);
    begin
      FCanvas2D.Pen:=Value;
    end;procedure TCanvas3D.SetPixels(x, y, z: Integer; const Value: TColor);
    begin
      with Point3DTo2D(x,y,z) do
      begin
        FCanvas2D.Pixels[x,y]:=Value;
      end;
    end;procedure TCanvas3D.SetViewHeight(const Value: Integer);
    begin
      FViewHeight := Value;
    end;procedure TCanvas3D.SetViewWidth(const Value: Integer);
    begin
      FViewWidth := Value;
    end;
    var
      i:Integer;
      Q:Double;procedure TCanvas3D.Sphere(x, y, z, r, hs, vs: Integer);
    var
      tx,ty,tz,hi:Integer;
      hn,vn,ht,vt,tr:Double;
      LastPoints:array of T2DPoint;
    begin
      hn:=RadianCount/(2*hs);
      vn:=RadianCount/(2*vs);
      SetLength(LastPoints,2*hs+1);
      vt:=0;
      while vt< RadianCount/2 do
      begin
        tz:=Round(FCosArray[Round(vt)]*r+z);
        tr:=FSinArray[Round(vt)]*r;
        ht:=0;
        hi:=0;
        tx:=Round(FCosArray[Round(ht)]*tr+x);
        ty:=Round(FSinArray[Round(ht)]*tr+y);
        with Point3DTo2D(tx,ty,tz) do
        begin
          FCanvas2D.MoveTo(x,y);
          if vt>0 then
          begin
            FCanvas2D.LineTo(LastPoints[Round(hi)].x,LastPoints[Round(hi)].y);
            FCanvas2D.MoveTo(x,y);
          end;
          LastPoints[Round(hi)].x:=x;
          LastPoints[Round(hi)].y:=y;
          Inc(hi);
        end;
        ht:=ht+hn;
        while ht<=RadianCount do
        begin
          tx:=Round(FCosArray[Round(ht)]*tr+x);
          ty:=Round(FSinArray[Round(ht)]*tr+y);
          with Point3DTo2D(tx,ty,tz) do
          begin
            FCanvas2D.LineTo(x,y);
            if vt>0 then
            begin
              FCanvas2D.LineTo(LastPoints[Round(hi)].x,LastPoints[Round(hi)].y);
              FCanvas2D.MoveTo(x,y);
            end;
            LastPoints[Round(hi)].x:=x;
            LastPoints[Round(hi)].y:=y;
            Inc(hi);
          end;
          ht:=ht+hn;
        end;
        vt:=vt+vn;
      end;
    end;initialization
      //---------------------------
      FRadianStep:=2*PI/RadianCount;
      Q:=0;
      for i:=Low(FCosArray) to High(FCosArray) do
      begin
        FCosArray[i]:=Cos(Q);
        FSinArray[i]:=Sin(Q);
        Q:=Q+FRadianStep;
      end;end.
    //以下是一个测试单元
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, StdCtrls, QQCanvas3D, ExtDlgs, jpeg;
    type  TForm1 = class(TForm)
        PaintBox1: TPaintBox;
        PaintBox2: TPaintBox;
        LoadPicBtn: TButton;
        OPD1: TOpenPictureDialog;
        ConverBtn: TButton;
        procedure FormCreate(Sender: TObject);
        procedure LoadPicBtnClick(Sender: TObject);
        procedure ConverBtnClick(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
        Ca3D:TCanvas3D;  end;var
      Form1: TForm1;implementation{$R *.dfm}
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Ca3D:=TCanvas3D.Create(PaintBox2.Canvas);
      Ca3D.ViewWidth:=PaintBox2.Width;
      Ca3D.ViewHeight:=PaintBox2.Height;
    end;procedure TForm1.LoadPicBtnClick(Sender: TObject);
    var
      Pic:TPicture;
    begin
      if OPD1.Execute then
      begin
        Pic:=TPicture.Create;
        Pic.LoadFromFile(OPD1.FileName);
        PaintBox1.Canvas.StretchDraw(PaintBox1.ClientRect,Pic.Graphic);
        Pic.Free;
      end;
    end;procedure TForm1.ConverBtnClick(Sender: TObject);
    var
      x,y,z:Integer;
    begin
      with PaintBox1,Canvas do
      for y:=0 to Height-1 do
      begin
        z:=0;
        for x:=0 to Width-1 do
        begin
          Ca3D.Pixels[x,y,z]:=Pixels[x,y];
          inc(z,5);
        end;
      end;     
    end;end.
      

  2.   

    你可以学习一下OPENGL或者是D3D,直接在内存中绘制3D效果,然后拷到屏幕上就行。
    代码...应该不超过50行。
      

  3.   

    不过你说的是想要算法啊
    由图像中任意一点(x,y)计算出相对于视点O(x0,y0,z0)的三维坐标A(X,Y,Z),将图像中假想和屏幕相交的面作交平面(z=0),计算OA和交平面的点A'(x',y',z'=0)。根据(x',y')取整后的位置累加,叠加(注意多点重复叠加时颜色敏感度的权)平均值作为最终颜色。
    每一个点算过来,计算量很大,我见过有人用汇编写,效果好一些,其实现在大部分这种工作都交给图形卡了,还是用opengl吧,呵呵
      

  4.   

    OPENGL 比较好用,不过很难理解里面的机理,还是买本算法书去看吧,不过用OPENGL用好了也不错了300多函数够你忙活的了!
      

  5.   

    就是远视图吧
    procedure TForm1.TiltBitmap(const InBitmap, OutBitmap: TBitmap;
      const WidthTop, WidthBottom: integer);
    const
      clBackColor = clBlack;
      BestQuality = True;
    var
      y, xWidthDiff, xWidthCurrentLine: Integer;
      d: Real;
    begin
      OutBitmap.PixelFormat := InBitmap.PixelFormat;
      if WidthTop > WidthBottom then
        OutBitmap.Width := WidthTop
      else
        OutBitmap.Width := WidthBottom;
      OutBitmap.Height := InBitmap.Height;
      OutBitmap.Canvas.Brush.Color := clblack;
      OutBitmap.Canvas.FillRect(OutBitmap.Canvas.ClipRect);
      OutBitmap.Canvas.CopyMode := cmSrcCopy;
      if BestQuality then
      begin
        {slower but better quality with color images}
        SetStretchBltMode(OutBitmap.Canvas.Handle, HALFTONE);
        SetBrushOrgEx(OutBitmap.Canvas.Handle, 0, 0, nil);
      end
      else
        {quicker but slightly lower quality}
        SetStretchBltMode(OutBitmap.Canvas.Handle, HALFTONE);
      OutBitmap.Canvas.CopyMode := cmSrcCopy;
      d := (WidthBottom - WidthTop) / OutBitmap.Height;  for y := 0 to OutBitmap.Height - 1 do
      begin
        xWidthCurrentLine := Trunc(WidthTop + d * y);
        xWidthDiff := (OutBitmap.Width - xWidthCurrentLine) div 2;
        OutBitmap.Canvas.CopyRect(Rect(xWidthDiff, y, xWidthDiff +
          xWidthCurrentLine, y + 1),
          InBitmap.Canvas, Rect(0, y, InBitmap.Width, y + 1));
      end;
    end;
    var
      InBitmap, outbitmap: Tbitmap;
    begin
      if Image1.Picture.Bitmap.Empty then
      begin
        ShowMessage('请加载图片');
        exit;
      end
      else
        InBitmap := TBitmap.Create;
      outbitmap := TBitmap.Create;
      InBitmap.Assign(image1.Picture.Bitmap);
      TiltBitmap(InBitmap, OutBitmap, 300, 600);
      image1.Picture.Bitmap.Assign(outbitmap);
      image1.Invalidate;
      InBitmap.Free;
      outbitmap.Free;
      

  6.   

    就像这个效果,号牌你从正面拍的时候是完全矩形的,但是安装到车上后,并且在车前面45度拍照的时候,效果就变成这样了http://www.jiaxinol.com/17359.bmp   ,我需要的就是根据正面的矩形,变换成侧面的这个矩形(只针对号牌,其他地方不用管),我用PlgBlt 实现了斜拉的效果,但是文字有锯齿了,如果解决?
      

  7.   

    是  http://www.jiaxinol.com/17359.jpg
      

  8.   

    1.要解决如何将矩形变形,就得了解投影变换,可以看看:
      http://topic.csdn.net/t/20020719/11/886049.html
      其中讨论的问题是你的逆问题:如何从非矩型投影转换为矩形,
      但二者的原理是一样的,作的都是投影变换.2.要解决文字锯齿状,要研究反锯齿算法.
      反锯齿算法任何计算机图形学书中都要讲到.在网上也很多,例如,可参考:
      http://topic.csdn.net/t/20040114/13/2662782.html3.严格讲,图像经过转动,原来的一个象素,一般都不会
      恰好变到新图像矩阵中的一个象素,而总会有一部分落到
      它四周的象素方格中.反过来说,新图像中的每一个象素,必定
      是原来图像几个像素共同变换得来的. 你要考虑每一个新图像
      象素如何“反锯齿”问题。
      为了较精确地绘制你的新图像,你要考虑的,就是如何找到
      变换成每一个新图像象素的原图像象素,并按它们在新象素中所
      占比例的大小,来进行加权平均.
      
      

  9.   

    请大家仔细看看http://www.jiaxinol.com/17359.jpg  这张图就彻底明白我说的意思了
      

  10.   

    我用PlgBlt 实现了斜拉的效果,但是文字有锯齿了,如果解决?
    另外哪位能搞到 印刷体仿宋字体,非正常仿宋体,如有字库能否发给我,谢谢 [email protected]
      

  11.   

    http://www.sz-qb.com/ttmmpp/t.htm
    达到这副图片的效果也是可以的,要求完整算法,可以给500分都可以