Delphi显示Opencv的Mat/IplImage图像

2017-06-19 19:44:37来源:CSDN作者:rocklee人点击

     先下载delphi opencv套件: https://github.com/Laex/Delphi-OpenCV

     打开opencv_classes工程, 增加如下 两个函数导出,用于mat->IplImage, IplImage->mat的转换, 因为delphi opencv这个套件里面的ocvView显示用的是IplImage。

ICLASS_API IplImage __stdcall ImageFromMat(Mat* mat){		IplImage lvRet=IplImage(*mat);			return lvRet;	}ICLASS_API IplImage* __stdcall CloneImageFromMat(Mat* mat){		IplImage* lvRet= cvCloneImage(&IplImage(*mat));		return lvRet;}
  这两个函数分别是从Mat转出IplImage和从Mat转出一个IplImage副本, 两者的区别在于, 副本是需要手动销毁的。
  再重新编译。


在delphi里面开一个unit, 加上这两个函数的导入:

 /// <summary>  /// 从MAT转换一份IplImage过来, 使用后无需销毁  /// </summary>function ImageFromMat(const mat: TOpenCVClass): TIplImage; stdcall;  external opencv_classes_lib name '[email protected]';/// <summary>/// 从MAT复制一份IplImage过来, 使用后需要手动cvReleaseImage销毁。/// </summary>function CloneImageFromMat(const mat: TOpenCVClass): pIplImage; stdcall;  external opencv_classes_lib name '[email protected]';

开一个project, 新建一个form, form data如下:

object Form1: TForm1  Left = 0  Top = 0  Caption = 'Form1'  ClientHeight = 314  ClientWidth = 536  Color = clBtnFace  Font.Charset = DEFAULT_CHARSET  Font.Color = clWindowText  Font.Height = -13  Font.Name = 'Tahoma'  Font.Style = []  OldCreateOrder = False  PixelsPerInch = 120  TextHeight = 16  object Button1: TButton    Left = 416    Top = 25    Width = 75    Height = 25    Caption = 'Button1'    TabOrder = 0    OnClick = Button1Click  end  object ocvView1: TocvView    Left = 8    Top = 16    Width = 385    Height = 241    Frames = <>  end  object Button2: TButton    Left = 416    Top = 56    Width = 75    Height = 25    Caption = 'Button2'    TabOrder = 2    OnClick = Button2Click  end  object Button3: TButton    Left = 416    Top = 96    Width = 75    Height = 25    Caption = 'Button3'    TabOrder = 3    OnClick = Button3Click  end  object Button4: TButton    Left = 416    Top = 136    Width = 75    Height = 25    Caption = 'Button4'    TabOrder = 4    OnClick = Button4Click  endend

对应的代码:

unit UMainForm;interfaceuses  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, GR32_Image,  ocv.highgui_c,  ocv.core_c,  ocv.core.types_c,  ocv.comp.types,  ocv.imgproc_c,  ocv.cls.imgproc,  uSafeClass,  ocv.cls.highgui, ocv.cls.core,  ocv.imgproc.types_c, Vcl.StdCtrls, ocv.comp.View, Vcl.ExtCtrls;type  TForm1 = class(TForm)    Button1: TButton;    ocvView1: TocvView;    Button2: TButton;    Button3: TButton;    Button4: TButton;    procedure Button1Click(Sender: TObject);    procedure Button2Click(Sender: TObject);    procedure Button3Click(Sender: TObject);    procedure Button4Click(Sender: TObject);  private    { Private declarations }  public    { Public declarations }  end;var  Form1: TForm1;implementation{$R *.dfm}uses uCvImgObj;procedure TForm1.Button1Click(Sender: TObject);varlvV:IocvImage;begin  lvV:=TocvImage.Create(cvLoadImage('resources/1.jpg')) as IocvImage;  ocvView1.DrawImage(lvV);end;procedure TForm1.Button2Click(Sender: TObject);var lvMat:IMat;lvCvImgObj:ICvImg;lvV:IocvImage;lvP:pIplImage;lvTmp:TIplImage;begin  //lvMat会自动释放  lvMat:=imread('resources/1.jpg');  lvTmp:=ImageFromMat(lvMat._InternalData);  //lvP也会自动释放,因为它们共享图像矩阵,这些内存由mat管理了。  lvP:[email protected];  lvV:=TocvImageEx.CreateClone(lvP) as IocvImage; //clone一份希望IocvImage用,然后TocvImageEx销毁的时候自己销毁它  ocvView1.DrawImage(lvV); //因为ocvView有一份独立的IplImage副本,所以能在wmpaint的时候正常显示图像end;procedure TForm1.Button3Click(Sender: TObject);var lvMat:IMat;lvCvImgObj:ICvImg;lvV:IocvImage;lvP:pIplImage;lvTmp:TIplImage;begin  //lvMat会自动释放  lvMat:=imread('resources/1.jpg');  lvTmp:=ImageFromMat(lvMat._InternalData);  //lvP也会自动释放,因为它们共享图像矩阵,这些内存由mat管理了。  lvP:[email protected];  //cvShowImage('aaa',lvP); //正常显示  lvV:=TocvImageEx.Create(lvP,rtNone) as IocvImage; //不能用这个,因为TocvImage销毁的时候会自动调用cvReleaseImage销毁IplImage对象,会引起AV,因为这个IplImage所对应的不需要销毁  ocvView1.DrawImage(lvV); //因为ocvView能够显示图像是在wmpaint的时候不断刷新图像,而这时候lvP指向的图像内存早就被mat释放掉了,所以看不到图像end;procedure TForm1.Button4Click(Sender: TObject);var lvMat:IMat;lvCvImgObj:ICvImg;lvV:IocvImage;begin  //lvMat会自动释放  lvMat:=imread('resources/1.jpg');  //lvP从Mat复制一份IplImage过来,使用后需要自己销毁  lvV:=TocvImageEx.Create(CloneImageFromMat(lvMat._InternalData),rtAll) as IocvImage; //TocvImageEx销毁的时候自己销毁它  ocvView1.DrawImage(lvV); //因为ocvView有一份独立的IplImage副本,所以能在wmpaint的时候正常显示图像end;end.

其中, button1Click显示了怎么通用从文件读入图像并显示

button2click演示了通过dll调用,从mat转出IplImage并用iocvImage的createClone方式制作副本显示到ocvView1上

button3click演示了为什么不能正常显示图像的原因, 但lvTmp在这个过程中是能正常使用的, 比如用途图像处理或图像保存等。

button4click演示了通过dll调用从mat转出一个IplImage副本,并用ocvView1显示出来。




最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台