zoukankan      html  css  js  c++  java
  • 图像处理时用的卷积函数

      做图像处理,最耗时间的运算应该就是卷积运算那一步了。以后如果有机会在用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指令效果就更好了,可惜这个我不太熟悉。
  • 相关阅读:
    session
    php增删改查,分页
    sql题
    php简单的数据增删改查
    php简单登录注册验证
    js题
    jQHTML(获取内容和属性)
    jQ效果(动画)
    Codeforces Round #460 (Div. 2): D. Substring(DAG+DP+判环)
    POJ 2891 中国剩余定理(不互素)
  • 原文地址:https://www.cnblogs.com/tiandsp/p/2793442.html
Copyright © 2011-2022 走看看