首页 > 编程语言 >为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍

为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍

时间:2022-12-26 23:06:23浏览次数:45  
标签:MFC QT img Image object Bitmap OpenCV data cv

        基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题。对于c++语系的程序员来说,一般来说有QT/MFC两种考虑。QT的确功能强大,特别是QML编写android界面很有一套,在树莓派上进行设计也很方便( ;但是使用QT的一个现实问题就是和现有平台的结合,比如客户需要将结果导出到excel中,使用QT就比较别扭(当然不是说不可以)。所以现在我一般这样来做:对于Android和PI,或者需要在Linux上运行的项目,使用QT编写界面,调用Opencv函数;对于需要在windows上运行的项目,使用MFC编写界面,直接就可以引用OpenCV。



        有人会吐槽MFC使用起来非常麻烦,这点我非常同意。但MFC经过这么多年的发展,今日仍有活力,并且短时间内不会消失。因为相比较其他一些所见即所得的语言和环境来说(QT/Csharp),mfc的消息映射机制和坐标体系等,的确有它的优势,对于图像处理程序来说尤其如此;加以积累,能够快速做出很多专业的东西;近期出现的ribbon界面也为mfc加分不少



       选择了MFC这个方向,思考图像处理程序问题,一般来说分为“处理图像”和"处理视频"两类:对于图像处理来说,我提供的GOPaint框架能够提供一个基本的静态图像处理框架;而GOMFCTemplate2则适合用来处理视频。这两种都 分别成功运用于多种视频处理项目中。



       但是这里我想更进一步:希望能够用Csharp编写界面,因为它更好用;但是又不想引入EmguCV类似的库,因为里面很多东西不是我需要的。那么最直接的方法就是使用Csharp调用基于Opencv编写的类库文件(Dll)的,我取名叫做​​GreenOpenCsharpWarper(GOCW)​​



       经过比较长时间的探索研究,目前的GOCW已经可以直接以函数的形式在内存中传递bitmap和Mat对象,达到了函数级别的应用。因为这里涉及到托管代码编写,也就是CLR程序编写,所以有比较复杂的地方;为了展现GOCW的优良特性,我编写实现GOGPY项目,也就是一个"Csharp编写界面,OpenCV实现算法的实时视频处理程序”,相关细节都包含其中。之所以叫“GPY”,是采集硬件这块,我采用了成像质量较好的高拍仪设备(GaoPaiYi)。



为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍_图像处理




为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍_System_02


       这里简单将最核心内容进行讲解。GOCW的核心问题,无非就是基于CLR之上的两个方向的数据流转换。核心函数为


Bitmap
^ GOClrClass
:
:testMethod(cli
:
:array
<
unsigned char
>
^ pCBuf1)

{
pin_ptr <System
:
:Byte
> p1
=
&pCBuf1[
0];

unsigned char
* pby1
= p1;

cv :
:Mat img_data1(pCBuf1
-
>Length,
1,CV_8U,pby1);

cv :
:Mat img_object
= cv
:
:imdecode(img_data1,IMREAD_UNCHANGED);
//获得数据到img_object中去

//处理过程///

cvtColor(img_object,img_object, 40);


/

Bitmap ^ bb
= MatToBitmap(img_object);

if ( !img_object.data)

return nullptr;
std :
:vector
<uchar
> buf;

cv :
:imencode(
".jpg", img_object, buf);

return bb;
}

以及



System
:
:Drawing
:
:Bitmap
^ MatToBitmap(
const cv :
:Mat
& img)

{
if (img.type() != CV_8UC3)

{
throw gcnew NotSupportedException( "Only images of type CV_8UC3 are supported for conversion to Bitmap");

}
//create the bitmap and get the pointer to the data

PixelFormat fmt(PixelFormat :
:Format24bppRgb);

Bitmap ^bmpimg
= gcnew Bitmap(img.cols, img.rows, fmt);

BitmapData ^data
= bmpimg
-
>LockBits(System
:
:Drawing
:
:Rectangle(
0,
0, img.cols, img.rows), ImageLockMode
:
:WriteOnly, fmt);

//byte *dstData = reinterpret_cast<byte*>(data->Scan0.ToPointer());

Byte *dstData
=
reinterpret_cast
<Byte
*
>(data
-
>Scan0.ToPointer());

unsigned char *srcData
= img.data;

for ( int row =
0; row
< data
-
>Height;
++row)

{
memcpy( reinterpret_cast
<
void
*
>(
&dstData[row
*data
-
>Stride]),
reinterpret_cast
<
void
*
>(
&srcData[row
*img.step]), img.cols
*img.channels());

}
bmpimg -
>UnlockBits(data);

return bmpimg;
}

 


而在chsarp中,直接


Bitmap b 
=
new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);

// If the image is upsidedown

b.RotateFlip(RotateFlipType.RotateNoneFlipY);
srcImage = b;

if (picPreview.Image != null)

picPreview.Image.Dispose();

//调用clr+opencv图像处理模块

MemoryStream ms =
new MemoryStream();
b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes = ms.GetBuffer();

Bitmap bitmap = client.testMethod(bytes);


就可以调用,并且获得结果。


 


以下内容为2017年更新的内容,适当参考:


一、CLR编写的DLL部分


1、按照正常方法引入Opencv;


2、提供接口函数,进行图像处理(这里只是实现了cvtColor,实际过程中可以用自己编写的复杂函数)


String
^ Class1
:
:Method(cli
:
:array
<
unsigned char
>
^ pCBuf1)

{
pin_ptr <System
:
:Byte
> p1
=
&pCBuf1[
0];

unsigned char
* pby1
= p1;

cv :
:Mat img_data1(pCBuf1
-
>Length,
1,CV_8U,pby1);

cv :
:Mat img_object
= cv
:
:imdecode(img_data1,IMREAD_UNCHANGED);

//处理过程/

cvtColor(img_object,img_object, 40);

/

if ( !img_object.data)

return nullptr;
//获得目录,保存文件

cv :
:imwrite(
"c:/Method.jpg",img_object);

return "c:/Method.jpg";

}

String ^ Class1
:
:Method2(cli
:
:array
<
unsigned char
>
^ pCBuf1)

{
pin_ptr <System
:
:Byte
> p1
=
&pCBuf1[
0];

unsigned char
* pby1
= p1;

cv :
:Mat img_data1(pCBuf1
-
>Length,
1,CV_8U,pby1);

cv :
:Mat img_object
= cv
:
:imdecode(img_data1,IMREAD_UNCHANGED);

//处理过程///

cvtColor(img_object,img_object, 6);

/

if ( !img_object.data)

return nullptr;
//获得目录,保存文件

cv :
:imwrite(
"c:/Method2.jpg",img_object);

return "c:/Method2.jpg";

}


二、Winform调用接口部分(TIP:不仅可以用Winform调用,asp.net/webservice都是可以调用的)


1、直接引用clr dll



为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍_System_03


2、编写helper文件(应该也可以叫做 warpper),通过外部IO的方法获取clr dll的文件


class GOCsharpHelper       
{
Class1 client = new Class1();
string strResult1 = null;
string strResult2 = null;
//输入参数是string或bitmap
public Bitmap ImageProcess(string ImagePath){
Image ImageTemp = Bitmap.FromFile(ImagePath);
return ImageProcess(ImageTemp);
}
//输出结果是bitmap
public Bitmap ImageProcess(Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes = ms.GetBuffer();
strResult1 = client.Method(bytes);
Image ImageResult = Bitmap.FromFile(strResult1);
return (Bitmap)ImageResult;
}
public Bitmap ImageProcess2(string ImagePath)
{
Image ImageTemp = Bitmap.FromFile(ImagePath);
return ImageProcess2(ImageTemp);
}
//输出结果是bitmap
public Bitmap ImageProcess2(Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes = ms.GetBuffer();
strResult2 = client.Method2(bytes);
Image ImageResult = Bitmap.FromFile(strResult2);
return (Bitmap)ImageResult;
}
public void Clear()
{
if (File.Exists(strResult1))
File.Delete(strResult1);
if (File.Exists(strResult2))
File.Delete(strResult2);
}
}

3、使用例子(注意控件的dispose):


 


private       void button2_Click(object sender, EventArgs e)      
{
if (pictureBox1.Image != null)
pictureBox1.Image.Dispose();
if (pictureBox2.Image != null)
pictureBox2.Image.Dispose();
Image image1 = gocsharphelper.ImageProcess( " E:/sandbox/logo.jpg");

pictureBox1.Image = image1;
Image image2 = gocsharphelper.ImageProcess2( "E:/sandbox/lena.jpg");

pictureBox2.Image = image2;

}

 


三、解释说明 


使用外部I/O不仅仅是权宜之计,实际上Opencv的Decode使用的就是外部I/O。就目前研究的水平来说,这是最稳定的。


目前搭建成功的框架已经能够完成“csharp调用opencv的”目标,并且在调试、参数传递方面都很强。


如果是处理静态图片,已经够用。


四、杀手程序


GOImageResearch:


使用这种方法编写的图像处理预分析程序。



为基于OpenCV的图像处理程序编写界面—关于QT\MFC\CSharp的选择以及GOCW的介绍_Image_04



标签:MFC,QT,img,Image,object,Bitmap,OpenCV,data,cv
From: https://blog.51cto.com/jsxyhelu2017/5971119

相关文章

  • 记录一次关于OpenCV的CmakeLists的探索
        编写基于OpenCV的图像处理程序,其中很重要的一道门槛就是编译OpenCV,应该说如果你对其中的内容如果不是很熟悉的话,即使是最简单粗暴的“两次configure,一次gene......
  • MFC -- 实现键盘HOOK
    一、新建一个MFC应用程序 二、选择资源视图,打开界面设置(IDD_KEYBOARDHOOK_DIALOG) 三、删除原有的控件,从工具箱添加一个按钮 四、修改按钮的标题属性,双击进入开始编写代码......
  • QT案例词典 -- 释放堆区空间及查询单词
    不是我不想,你上学我上班,我耽误你前程似锦,你耽误我成家立业,我的眼里都是烟花和生活,你的眼里都是未来和希望。。。---- 网易云热评一、释放堆区空间voidfree_dict(structd......
  • QT案例词典 -- 存储内容及遍历
    遗憾的是,两个人不能在一起,却偏偏相遇。。。---- 网易云热评一、字典内容就三个词a:第一个字母b:第二个字母C:第三个字母#defineMAX3 二、定义一个词的机构体structdict{......
  • QT案例IDE编写 -- 创建项目
    让你心动的人,给不了你心安的感觉,让你心安的人,给不了你心动的感觉,或许,这就是答案。。。---- 网易云热评一、新建QT项目1、选择Qt Widgets Application,文件--新建项目。一......
  • MFC应用程序对话框架构
    喜欢大概就是:在我们俩对视的一瞬间,我突然就避开了你的视线,而当你走过去的时候,我却在你背后看了你好久。。。---- 网易云热评一、新建MFC应用程序项目,项目名称不能用中文 ......
  • Qt实现扇形图
    #include"donutbreakdownchart.h"#include"mainslice.h"#include<QtCharts/QPieSlice>#include<QtCharts/QPieLegendMarker>QT_CHARTS_USE_NAMESPACEDonutBreakdownChar......
  • 流水账——利用MFC开发的小软件
    本篇是记录硕士期间开发的小软件。图形界面是基于MFC开发的,其中利用了​​OpenCV​​还有MySQL数据库。下面开始记录流水账式开发过程:MFC框架新建MFC项目,基于单文档,MFC标准......
  • (GO_GTD_2)基于OpenCV和QT,建立Android图像处理程序
    一、综述   如何采集图片?在windows环境下,我们可以使用dshow,在linux下,也有ffmpeg等基础类库,再不济,opencv自带的videocapture也是提供了基础的支撑。那么在andoird......
  • 使用opencv自带的融合函数
    [wiki,blog]使用opencv自带的融合函数/*M///////IMPORTANT:READBEFOREDOWNLOADING,COPYING,INSTALLINGORUSING.////By......