当前位置: 首页 > news >正文

图像处理时用的卷积函数

  做图像处理,最耗时间的运算应该就是卷积运算那一步了。以后如果有机会在用c++做图像处理的项目的话,那么这个卷积部分还是要优化的。Matlab因为是验证算法,其实是没必要优化的。所以我就把卷积这一部分单独列出一个函数,用汇编实现了。我可是电子工程出身,汇编当然不在话下。

  函数是用汇编写的,用的是c++内嵌asm汇编,相同功能的c++代码也实现了,不过注释掉了,去掉注释能得到相同的结果。

  读和显示图像用了opencv函数库,话说上一个项目结束之后好像就没怎么用过这个库了,毕竟,单单调用库中的函数是没办法真正理解原理的。

#include <iostream>
#include "cv.h"
#include "highgui.h"
using namespace std;

//*img是图像数据,i_h是图像的高,i_w是图像的宽
//*m是卷积模板,m_h是模板的高,m_w是模板的宽
//x,y是在图像(x,y)坐标处卷积
//返回卷积的值
int conv(int *img,int i_h,int i_w,int *m,int m_h,int m_w,int y,int x)
{
    int re;
    int sum1;
    int sum2;
    int half_m_w;
    int half_m_h;
    int i;
    int j;
    int ii;
    int jj;
    __asm
    {
        mov        re,0;
        mov        sum1,0;
        mov        sum2,0;

        mov        eax,m_w;        //half_m_w=(m_w-1)/2;
        dec        eax;
        mov        bl,2;
        div        bl;
        mov        ah,0;
        mov        half_m_w,eax;

        mov        eax,m_h;        //half_m_h=(m_h-1)/2;
        dec        eax;
        mov        bl,2;
        div        bl;
        mov        ah,0;
        mov        half_m_h,eax;

        mov        ecx,m_w;        //m_w*h_h
        imul      ecx,m_h;
        mov        eax,0;

label1:
        mov        ebx,m;            //        for (i=0;i<m_w*m_h;i++)                                                                                                                    
        add        eax,[ebx];        //        {
        add        ebx,4;            //            sum2+=m[i];
        dec        ecx;            //        }
        jnz        label1;
        mov        sum2,eax;

        mov        i,0;
        mov        ii,0;
        mov        eax,y;            //i=y-half_m_h;
        sub        eax,half_m_h;
        mov        i,eax;

label2:
        mov        j,0;
        mov        jj,0;
        mov        eax,x;            //j=x-half_m_w;
        sub        eax,half_m_w;
        mov        j,eax;

label3:        
        mov        ebx,img;        //每次循环重新赋值img基址
        mov        edx,m;            //每次重新赋值m基址

        mov        eax,i;            //i*i_w+j
        imul    eax,4;
        imul    eax,i_w;
        mov        ecx,j;
        imul    ecx,4;
        add        eax,ecx;
        add        ebx,eax;

        mov        eax,ii;            //ii*m_w+jj
        imul      eax,4;
        imul      eax,m_w;
        mov        ecx,jj;
        imul      ecx,4;
        add        eax,ecx;
        add        edx,eax;

        mov        eax,[ebx];        //sum1+=img[i*i_w+j]*m[ii*m_w+jj];
        imul      eax,[edx];
        add        eax,sum1;
        mov        sum1,eax;

        mov        eax,jj;            //jj++
        inc        eax;
        mov        jj,eax;

        mov        eax,x;            //j?<x+half_m_w
        add        eax,half_m_w;
        mov        ecx,eax;
        sub        ecx,j;
        mov        eax,j;            //j++
        inc        eax;
        mov        j,eax;

        test      ecx,ecx;
        jnz        label3;
         
        mov        eax,ii;            //ii++
        inc        eax;
        mov        ii,eax;

        mov        eax,y;            //i?<y+half_m_h
        add        eax,half_m_h;
        mov        ecx,eax;
        sub        ecx,i;
        mov        eax,i;            //i++
        inc        eax;
        mov        i,eax;

        test      ecx,ecx;
        jnz        label2;

        mov        eax,sum1;        //sum1/sum2
        mov        ebx,sum2;
        div        bl;
        mov        ah,0;
        mov        re,eax;

    }    
    /*
    half_m_h=(m_h-1)/2;
    half_m_w=(m_w-1)/2;
    sum1=0;
    sum2=0;
    for (i=0;i<m_w*m_h;i++)
    {
        sum2+=m[i];
    }

    for (i=y-half_m_h,ii=0;i<=y+half_m_h;i++,ii++)
    {
        for (j=x-half_m_w,jj=0;j<=x+half_m_w;j++,jj++)
        {
            sum1+=img[i*i_w+j]*m[ii*m_w+jj];
        }
    }
    re=int(sum1/sum2);
    */
    return re;
}

int main()
{
    IplImage *image;
    CvScalar s;
    image=cvLoadImage("C:/Users/tc/Documents/Visual Studio 2010/Projects/vm/Debug/lena.jpg",0);

    int *img;
    img=new int[image->height*image->width];

    for (int i=0;i<image->height;i++)
    {
        for (int j=0;j<image->width;j++)
        {
            s=cvGet2D(image,i,j);
            img[i*image->width+j]=(int)s.val[0];
        }
    }

    int *m;
    m=new int[9];
    for (int i=0;i<9;i++)
    {
        m[i]=1;
    }

    for (int i=1;i<image->height-1;i++)
    {
        for (int j=1;j<image->width-1;j++)
        {
            s=cvGet2D(image,i,j);
            s.val[0]=conv(img,image->height,image->width,m,3,3,i,j);
            cvSet2D(image,i,j,s);
        }
    }

    cvNamedWindow("lena",1);
    cvShowImage("lena",image);

    cvWaitKey(0);
    cvReleaseImage(&image);
    cvDestroyAllWindows();
    delete[] img;
    delete[] m;
    return 0;
}

注:要是使用mmx,sse指令效果就更好了,可惜这个我不太熟悉。

相关文章:

  • asp.net web api
  • 各浏览器对页面外部资源加载的策略
  • 收藏 c#小函数
  • 解决Page.FindControl方法找不到指定控件 转
  • 二台电脑之间数据库文件进行备份
  • Oracle 发布 NoSQL 数据库
  • IBM Java多线程 - 5.同步详细信息
  • 收藏一个数学的C++算法的好博客
  • delphi 脚本引擎比较
  • Postgresql数据库的恢复(Console)
  • C#程序集系列07,篡改程序集
  • 线程系列08,实现线程锁的各种方式,使用lock,Montor,Mutex,Semaphore以及线程死锁
  • Android SDK Manager 无法更新的解决办法
  • java电子商务系统源码 Spring MVC+mybatis+spring cloud+spring boot+spring security
  • 软件加密与解密
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 78. Subsets
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Java教程_软件开发基础
  • js ES6 求数组的交集,并集,还有差集
  • Promise面试题2实现异步串行执行
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • 多线程 start 和 run 方法到底有什么区别?
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 三栏布局总结
  • 它承受着该等级不该有的简单, leetcode 564 寻找最近的回文数
  • 我建了一个叫Hello World的项目
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 译米田引理
  • Java总结 - String - 这篇请使劲喷我
  • puppet连载22:define用法
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • 进程与线程(三)——进程/线程间通信
  • # C++之functional库用法整理
  • (+4)2.2UML建模图
  • (16)Reactor的测试——响应式Spring的道法术器
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (全注解开发)学习Spring-MVC的第三天
  • (三)c52学习之旅-点亮LED灯
  • (十三)Flask之特殊装饰器详解
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .Net Remoting常用部署结构
  • .net 简单实现MD5
  • .Net的C#语言取月份数值对应的MonthName值
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • .NET中的十进制浮点类型,徐汇区网站设计
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解
  • [APUE]进程关系(下)
  • [EFI]Dell Inspiron 15 5567 电脑 Hackintosh 黑苹果efi引导文件
  • [HDU] 1054 Strategic Game 入门树形DP
  • [IDF]啥?