基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题。对于c++语系的程序员来说,一般来说有QT/MFC两种考虑。QT的确功能强大,特别是QML编写android界面很有一套(https://www.cnblogs.com/jsxyhelu/p/8286476.html),在树莓派上进行设计也很方便(https://www.cnblogs.com/jsxyhelu/p/7839062.html);但是使用QT的一个现实问题就是和现有平台的结合,比如客户需要将结果导出到excel中,使用QT就比较别扭(当然不是说不可以)。所以现在我一般这样来做:对于Android和PI,或者需要在Linux上运行的项目,使用QT编写界面,调用Opencv函数;对于需要在windows上运行的项目,使用MFC编写界面,直接就可以引用OpenCV。
        有人会吐槽MFC使用起来非常麻烦,这点我非常同意。但MFC经过这么多年的发展,今日仍有活力,并且短时间内不会消失。因为相比较其他一些所见即所得的语言和环境来说(QT/Csharp),mfc的消息映射机制和坐标体系等,的确有它的优势,对于图像处理程序来说尤其如此;加以积累,能够快速做出很多专业的东西;近期出现的ribbon界面也为mfc加分不少(https://www.cnblogs.com/jsxyhelu/p/9209052.html
       选择了MFC这个方向,思考图像处理程序问题,一般来说分为“处理图像”和"处理视频"两类:对于图像处理来说,我提供的GOPaint框架(https://www.cnblogs.com/jsxyhelu/p/6440910.html)能够提供一个基本的静态图像处理框架;而GOMFCTemplate2(https://www.cnblogs.com/jsxyhelu/p/GOMFCTemplate2.html)则适合用来处理视频。这两种都分别成功运用于多种视频处理项目中。
       但是这里我想更进一步:希望能够用Csharp编写界面,因为它更好用;但是又不想引入EmguCV类似的库,因为里面很多东西不是我需要的。那么最直接的方法就是使用Csharp调用基于Opencv编写的类库文件(Dll)的,我取名叫做GreenOpenCsharpWarper(GOCW)
       经过比较长时间的探索研究,目前的GOCW已经可以直接以函数的形式在内存中传递bitmap和Mat对象,达到了函数级别的应用。因为这里涉及到托管代码编写,也就是CLR程序编写,所以有比较复杂的地方;为了展现GOCW的优良特性,我编写实现GOGPY项目,也就是一个"Csharp编写界面,OpenCV实现算法的实时视频处理程序”,相关细节都包含其中。之所以叫“GPY”,是采集硬件这块,我采用了成像质量较好的高拍仪设备(GaoPaiYi)。
       这里简单将最核心内容进行讲解。GOCW的核心问题,无非就是基于CLR之上的两个方向的数据流转换。核心函数为
Bitmap];
    ,CV_8U,pby1);
    cv);
    
    /////////////////////////////////////////////////////////////////////////////////
    Bitmap^ bb = MatToBitmap(img_object);
    if (!img_object.data)
        return nullptr;
    std::vector<uchar> buf;
    cv::imencode(".jpg", img_object, buf);
    return bb;
}
以及
System, , img.cols, img.rows), ImageLockMode; 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];
     ,CV_8U,pby1);
     cv);
     ];
    ,CV_8U,pby1);
    cv);
 /////////////////////////////////////////////////////////////////////////////////
    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
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的介绍的更多相关文章

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

            基于OpenCV编写图像处理项目,除了算法以外,比较重要一个问题就是界面设计问题.对于c++语系的程序员来说,一般来说有QT/MFC两种考虑.QT的确功能强大,特别是QML编写andr ...

  2. Java基于opencv实现图像数字识别(五)—投影法分割字符

    Java基于opencv实现图像数字识别(五)-投影法分割字符 水平投影法 1.水平投影法就是先用一个数组统计出图像每行黑色像素点的个数(二值化的图像): 2.选出一个最优的阀值,根据比这个阀值大或小 ...

  3. Java基于opencv实现图像数字识别(四)—图像降噪

    Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...

  4. Java基于opencv实现图像数字识别(三)—灰度化和二值化

    Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...

  5. Java基于opencv实现图像数字识别(二)—基本流程

    Java基于opencv实现图像数字识别(二)-基本流程 做一个项目之前呢,我们应该有一个总体把握,或者是进度条:来一步步的督促着我们来完成这个项目,在我们正式开始前呢,我们先讨论下流程. 我做的主要 ...

  6. Java基于opencv实现图像数字识别(一)

    Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...

  7. Java基于opencv—矫正图像

    更多的时候,我们得到的图像不可能是正的,多少都会有一定的倾斜,就比如下面的 我们要做的就是把它们变成下面这样的 我们采用的是寻找轮廓的思路,来矫正图片:只要有明显的轮廓都可以采用这种思路 具体思路: ...

  8. 【图像处理】基于OpenCV实现图像直方图的原理

    背景 图像的直方图是衡量图像像素分布的一种方式,可以通过分析像素分布,使用直方图均衡化对图像进行优化,让图像变的清晰. opencv官方对图像直方图的定义如下: 直方图是图像中像素强度分布的图形表达方 ...

  9. Java基于opencv实现图像数字识别(五)—腐蚀、膨胀处理

    腐蚀:去除图像表面像素,将图像逐步缩小,以达到消去点状图像的效果:作用就是将图像边缘的毛刺剔除掉 膨胀:将图像表面不断扩散以达到去除小孔的效果:作用就是将目标的边缘或者是内部的坑填掉 使用相同次数的腐 ...

随机推荐

  1. vmware您无权输入许可证密钥,请请使用系统管理员账户重试

    vmware15,输入许可证时报“您无权输入许可证密钥,请请使用系统管理员账户重试”,切换到Administrator以后,并没有什么作用. 网上的各种进入cmd的方法也无效. 后来发现,只要是已经存 ...

  2. 报文分析6、ARP报头结构

    ARP报头结构   硬件类型 协议类型 硬件地址长度 协议长度 操作类型 发送方的硬件地址(0-3字节) 源物理地址(4-5字节) 源IP地址(0-1字节) 源IP地址(2-3字节) 目标硬件地址(0 ...

  3. weakhashmap简单理解

    map中的key(注意String,和元数据作key有特殊性),gc后会被立马干掉, key被干掉后,其对应的entry将被存入queue中 /** * Reference queue for cle ...

  4. python基础3 条件判断 if嵌套

    if单向判断: stonenumber=6#为宝石数量赋值 if stonenumber>=6: #条件:如果你拥有的宝石数量大于等于6个 print('你拥有了毁灭宇宙的力量') #结果:显示 ...

  5. 类的命名空间&组合

    类的命名空间◆类中的静态变量可以被类调用也可以被对象调用◆对不可变数据类型来说,类变量最好用类名操作 class Person: money = 0 mother = Person() father ...

  6. java中使用JDBC的preparedStatement批处理数据的添加

    在项目中我们偶尔可能会遇到批量向数据库中导入数据,如果批处理的情况较多的情况下可以使用spring batch,如果只是一个导入功能的话可以考虑使用jdbc的preparedStatement处理. ...

  7. MIPI-Layout说明(转载)

    转载于:http://www.ccm99.com/thread-3713-1-1.html 前言:随着新的总线协议不断提高信号速率,如今的PCB 设计人员需要充分理解高速布线的要求并控制PCB 走线的 ...

  8. Sql题面试题

    哪位大神会此题,请给出答案,十分感谢! 哪位大神会此题,请给出答案,十分感谢!

  9. 关于优先队列浅析(priority_queue)

    优先队列 greater与less,自定义还有结构体(可以设置2层优先级)  模板; 下面废话不多说直接上程序 注释的很明白 #include<iostream> #include< ...

  10. js优化 前端小白适用

    注意啦,前端初学者适合看的js优化,当你看我的优化认为太low,那么恭喜,你已经脱离初学者了. 首先这边我觉得分享的还是以js为主,前端性能优化,我认为最重要的还是js,因为js是一门解释型的语言,相 ...