精华内容
下载资源
问答
  • 文本聚类平移算法的点问题

    千次阅读 2006-10-30 16:45:00
    文本聚类平移算法的点问题文本处理,我的最爱---题记大概一个月前 10b lobster 也和我聊起过卢亮介绍过的平移算法,详细的介绍可以看这里:卢亮的blog。记得当时第二天就看到了carrot2的发布,carrot2 上使用了...
    文本聚类平移算法的几点问题
    文本处理,我的最爱---题记

    大概一个月前 10b lobster 也和我聊起过卢亮介绍过的平移算法,
    详细的介绍可以看这里:卢亮的blog。记得当时第二天就看到了carrot2的发布,carrot2 上使用了多种聚类的算法

    有些人对平移算法嗤之以鼻,比如这位。在我看来,一个算法有没有效果,要看这个算法的前提和假设,大炮打小鸟怎么瞄也不带劲儿。在文本处理领域中,比如,中文分词,特别是文本聚类的算法上从来没有一个算法可以解决所有问题,很多解决方案都是采用多个算法取长补短来达到综合效果的。

    昨天写关于标签和书签的blog时想到,在改善新闻阅读器的文章分类也许平移算法用的上。周末便用了半天做了一个单向移动的平移算法。

    平移算法,要考虑这个算法适用的范围,这个是前提。我实现的平移算法和卢亮的目的不同,类似于我的:未登录词识别

    在算法的具体设计上,还需要考虑以下几个问题:
    1、窗口大小,窗口借用了tcp发包的窗口的概念,就是确认有效匹配的长度;
    2、平移的方向。我下面例子只实现了单向移动;
    3、效率问题,平移算法涉及了大量的比较,找到一个最短的比较边界还挺重要;

    下面是一份平移算法的原始结果,找出所有it公司的人名,感觉还可以。进一步处理后,就可以投入实际应用了:



    B2C,移动不,Google在中国,IT公司,Web1.0,凭什么,任何关系,不好 ,鲍尔默,有三大,现在的, 网易,在中国没,视频网,的名义,是一种,新浪博客,200,ay合作,是个很,马云雅,联想CEO, 新浪,干什么,第一 ,大的一,2.0 ,思文凯,笔记本,eb 2.0,程天宇,王建宙,721,软件产业,在社区,离不开,更重要,Web 2.0,商业化,年博客网,陈彤新,陈一舟,徐静蕾,是一个,web,绝对领,马云网络,CEO马,未来5,网不是,搜索引擎,商业模式,爱立信,做企业,技术不,互联网上,Donews,000万,1000万,李善友,惠普CEO,两年后,投资者,与百度,方兴东互联网,年时间,于技术,的竞争,赫德我,Linux,思科CEO钱伯斯,Web,新联想,我们不,不排除,英特尔CEO,对互联网,杨元庆,鲍尔默微软,可怕的,eBay,互联网创新,泼冷水,投资游戏,把自己,上3G,而不是,互联网产,ube,动互联网,.0 ,思维 ,You,惠普CEO赫德,没有失,的时候,称目前,2.0,1.0是,戴尔CEO,价格战,评论马云, 但是,富豪榜,黄光裕,创业者,新浪的,IDG,我不是,刘克丽,李志高,eBay的,不存在,中国IT,TCL,倪光南,博客的,服务将,风险投资,中国互联网,是Web,0美元,祝志军,曹国伟新浪,张朝阳互联网,IT网站的,eb2.0,周鸿袆,年后要,中移动,WiMAX,周鸿祎风,姜奇平, YouTube,团队 ,igg,规模并购,的威胁,WAPI,掌门人,国公司,张朝阳,鲍尔默微软有,游戏是,Live,尼葛洛庞帝,IPTV,CDMA,曹国伟,犯的错,喻国明,微软C,李开复,丁磊网易将,人博客,广告是,什么都,2.0发展,公司 ,微软有, Web,施密特,国互联网,500,宫玉国,陈永正,在中国,低估了,CEO王,柳传志, 不会,盖茨Google,是未来,Web2.0,薪水一,娱乐的,盖茨公,李彦宏,错误 ,李进良,乔布斯,Xbox,.0的,吴世雄,软件业,IBM,Google CEO,张朝阳博客,5年内,总裁李,很杰出,微软的,新掌门,微软CEO鲍尔默,“抄袭”,500万,的商业,最好的,齐向东,3721,e搜索,微软 CEO,周鸿祎,称百度,中搜CEO陈沛,赛门铁克,小灵通,上市 ,是微软,周鸿祎与, 没有,国软件,庞升东我,新高 ,log,吕本富,陈天桥,中国最,Digg创始人,竞争对手,中国有,吕伟钢,杨致远,犯的错误,史玉柱,百度不,张向宁,lexa,中国3G,将取代,运营商,网站并购,成网络,3G标准,5年后,曹国伟新,王建宙中移动,最困难,CEO,有什么,施振荣,天使投资,王建宙中,00万,李焜耀,收购 YouTube,王雷雷,垄断的,博客不,有今天,英特尔,网络泡沫,李彦宏 ,06年,副总裁,IT网站,本市场,传统媒,Google施密特,王志东,蔡文胜,要坚持,一定能赢,杨元庆联想,没什么,模仿印度,将继续,Web ,网CEO,Google中国,潘石屹,来不是,新浪总编,马化腾, CEO,视频是,做娱乐,六间房,并不是,粉丝网,国际化,收购要,董事会,百度李彦宏,Google,默多克,金蝶徐少春,赛门铁克CEO,2.0 的,.0是,不看好,总编辑,李学凌,1.0,反流氓软件,做三件事,网民都,李东生,副总编,高群耀,是如何,张朝阳不,新兴市场,张本伟,盖茨的,王晓初,惠特曼,企业的,副总裁李,Google还,网络成,网络媒体,Blog,100, 不看好,电子商务,比尔·盖茨, 1.0,明星博客,陈天桥盛大,当当网,创始人W,罗林斯,CEO网络,董事长,联想C,王定标,马云称,古永锵,项立刚,尔CEO,新媒体,不可能, CEO谈,投资人,任正非,雄我不,是错误,后Google,创业的,MSN,郭凡生,微软副总裁,新技术, google,阚凯力,互联网, Web2.0,多的是, 汪延,江南春,中国电信,田溯宁,看好W,新浪总编辑陈彤,什么中国,流氓软件,门户网站,张瑞敏,创始人,的IT,时最易犯,三大因素推动互联网未来发展,将是新,争议人物,周韶宁,五年内,的生活,创新 ,过多少,李开复Google,Vista,10年,中国总裁,中国不, 2.0,马雪征,黄明生,方兴东,钦佩的,周鸿一,两年内,eBay合作,把自己当,中国网,汤美娟,雅虎中国,Mysee高燃,网CEO李,王吉鹏,网络游戏,Google收购YouTube,不是一,TOM,徐东英,



    怎么样感觉还可以吧。

    我正在实现一个新闻句子提取引擎,做好后放到新闻阅读器里,这样查看高燃语录(2005-2006语录)的时候,可能会更方便。



       


    展开全文
  • 平移变换

    千次阅读 2017-11-26 09:58:41
    平移变换 原文: http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html CSDN完整版专栏: http://blog.csdn.net/column/details/13062.html 背景 从这个教程开始我们开始研究各种各样的图形...

    教程6:

    平移变换

    原文: http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html

    CSDN完整版专栏: http://blog.csdn.net/column/details/13062.html


    背景

    从这个教程开始我们开始研究各种各样的图形变换,图形变换就可以让一个3d物体在屏幕中变换的的时候看上去保持有深度的错觉,也就是立体的投影效果。实现立体效果的方法是使用一个经过多次相乘的变换矩阵得到的最终变换矩阵来和顶点的位置再相乘,这样得到3d物体的一个多次变换后的最终复合变换效果。后面每个教程将专门研究一种变换。

    这里我们先看一下平移变换,使一个物体沿着一个任意长度任意方向的向量平移,比如说让一个三角形从左边移动到右边:

    这里写图片描述

    在之前顶点着色器知识的基础上我们可以想到实现平移的一种办法是设置一个偏移向量(这里就是- 1,1 了),并把这个便宜向量定义成一致变量然后传递给shader让每一个顶点按照那个偏移向量移动即可。但这样就打破通过乘以一个经过多个变换矩阵相乘得到的复合变换矩阵来进行复合变换的统一性了。另外,如果平移变换变换不是一系列复合变换的第一个的话,你要先乘以平移变换之前的几个变换的复合变换矩阵,然后按照上面的方法平移图形,然后再乘以平移变换后面的复合变换矩阵(如果不止一个平移变换那么就要继续分解更繁琐了orz…)。 
    一个更好的办法是找到一个表示平移变换的矩阵,并加入到复合变换中作为复合变换中的其中一种变换。可是就上面的三角形平移例子,我们能找到一个矩阵和三角形左下角的点(0,0)相乘之后得到结果(1,1)吗?事实上是不可能找到这样一个2维矩阵的(同样对于点(0,0,0)也不可能找到这样一个符合要求的3维矩阵)。统一的说,我们是想找到这样一个矩阵,对于给定的点P(x,y,z)和平移向量V(v1,v2,v3),能够使 M * P = P1(x+v1, y+v2, z+v3) ,简单地说就是矩阵M将P转换成了P+V。在结果向量P1中我们可以看到每个分量是P和V每个分量对应相加的和,结果向量P1的+号左侧来自P本身,对于得到P本身的向量应该这样: 
    I * P = P(x,y,z) 。所以我们应该从得到本身开始来调整变换矩阵得到结果矩阵右侧相加结果(…+V1, …+V2, …+V3)的最终变换矩阵。首先自身变换矩阵的样子如下:

    这里写图片描述

    我们想修改这个自身变换矩阵使结果变成这样子:

    这里写图片描述

    如果我们坚持用3x3矩阵好像不可能得到想要的结果,但如果改成4x4矩阵我可以这样得到想要的结果:

    这里写图片描述

    这样使用一个4维向量表示一个3维向量叫做齐次坐标,这在3d图形学中很常用也很有用,第四个分量称作“w”。事实上,我们之前教程中看到的内部shader符号变量gl_Position就是一个4维向量,第四个分量“w”在从3d到2d的投影变换中起着关键作用。通常对于表示点的矩阵会让w=1,而对于表示向量的矩阵会让w=0,因为点可以被做变换而向量不可以,你可以改变一个向量的长度和方向,但是长度和方向一样的所有向量都是相等的,不管他们的起点在哪里,所以我们可以把所有的向量起点放到原点来看。对于向量设置w=0然后乘以变换矩阵会得到和自身一样的向量。

    源代码详解

    (1)struct Matrix4f { 
    float m[4][4]; 
    };

    我们在math_3d这个头文件中添加4维矩阵的定义,方便以后的矩阵变换用。

    (2)GLuint gWorldLocation;

    我们用这个句柄来获取shader中的“世界”平移变换矩阵一致变量的引用。用“世界”来形容的原因是我们要做的是把物体移动到我们虚拟“世界”坐标系中的某个位置。

    (3) 
    Matrix4f World; 
    World.m[0][0] = 1.0f; World.m[0][1] = 0.0f; World.m[0][2] = 0.0f; World.m[0][3] = sinf(Scale); 
    World.m[1][0] = 0.0f; World.m[1][1] = 1.0f; World.m[1][2] = 0.0f; World.m[1][3] = 0.0f; 
    World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f; 
    World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f;

    在渲染函数中我们按照上面介绍的来设置这个矩阵,设置v2和v3为0保持在Y和Z轴上不变化,设置v1为上个教程中sin函数得到的值,这样可以让物体在X轴上在-1到1之间来回平滑的移动。 
    现在我们要将这个矩阵加载到shader当中。

    (4)glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]);

    这是另外一个使用glUniform*函数将数据加载到shader一致变量中的例子。这个函数定义的可以加载4x4矩阵数据,还可以加载像2x2,3x3,3x2,2x4,4x2,3x4和4x3这样的矩阵。 
    第一个参数是一致变量的位置(在shader编译后使用glGetUniformLocation()获取);第二个参数指的是我们要更新的矩阵的个数,我们使用参数1来更新一个矩阵,但我们也可以使用这个函数在一次回调中更新多个矩阵;第三个参数通常会使新手误解,第三个参数指的是矩阵是行优先还是列优先的。行优先指的是矩阵是从顶部开始一行一行给出的,而列优先是从左边一列一列给出的。C/C++中默认是行优先的。也就是说当年你构建一个二维数组时,在内存中是一行一行存储的,顶部的行在更低的地址区。比如下面的矩阵:

    int a[2][3]; 
    a[0][0] = 1; 
    a[0][1] = 2; 
    a[0][2] = 3; 
    a[1][0] = 4; 
    a[1][1] = 5; 
    a[1][2] = 6;

    这个矩阵看上去和下面一样:

    1 2 3

    4 5 6

    在内存中的排布就像:1 2 3 4 5 6(1在低地址)。 
    所以我们glUniformMatrix4fv()函数的第三个参数是GL_TRUE,因为我们提供的矩阵是行优先的。我们也可以设置第三个参数为GL_FALSE,但同时我们要将我们的矩阵转置(在C/C++内存布局中会保持不变,但OpenGL中会认为前四个值是一个矩阵的列);第四个参数是内存中矩阵的起始地址。

    剩下的代码是shader脚本了:

    (5)uniform mat4 gWorld;

    这是一个4x4的矩阵的一致变量,也有mat2和mat3。

    (6)gl_Position = gWorld * vec4(Position, 1.0);

    在顶点缓冲区中三角形的顶点位置是一些3维的向量,我们讨论后这里需要一个值为1的第四个分量。有两种方式:要么直接在顶点缓冲区将顶点用4维向量表示,要么在顶点着色器中再添加第4个分量,但第一个方式没啥优势,浪费内存罢了,每个顶点要额外浪费4bytes空间。后者在顶点着色器阶段再添加第4个分量会更高效,在GLSL中使用’vec4(Position, 1.0)’来实现。我们将变换矩阵和那个向量相乘然后将结果赋给gl_Position。 
    总之,在每一帧中我们都产生一个变换矩阵将X轴的值在-1和1之间来回变换。着色器使用那个变换矩阵和每个顶点的位置相乘从而使图形整体左右摆动。多数情况下在顶点着色器变换后三角形的一边会超出单位盒子边界,然后裁剪器会把超出的一侧裁剪掉,我们只能看到在单位盒子里面的图形。

    示例Demo

    
    #include <stdio.h>
    #include <string.h>
    
    #include <math.h>
    #include <GL/glew.h>
    #include <GL/freeglut.h>
    
    #include "ogldev_util.h"
    #include "ogldev_math_3d.h" // 从这个教程开始要用到Metrix4x4矩阵的数据结构了
    
    GLuint VBO;
    // 平移变换一致变量的句柄引用
    GLuint gWorldLocation;
    
    const char* pVSFileName = "shader.vs";
    const char* pFSFileName = "shader.fs";
    
    
    static void RenderSceneCB()
    {
        glClear(GL_COLOR_BUFFER_BIT);
    
        static float Scale = 0.0f;
    
        Scale += 0.001f;
    
        // 4x4的平移变换矩阵
        Matrix4f World;
    
        World.m[0][0] = 1.0f; World.m[0][1] = 0.0f; World.m[0][2] = 0.0f; World.m[0][3] = sinf(Scale);
        World.m[1][0] = 0.0f; World.m[1][1] = 1.0f; World.m[1][2] = 0.0f; World.m[1][3] = 0.0f;
        World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f;
        World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f;
    
        // 将矩阵数据加载到shader中
        glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]);
    
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    
        glDrawArrays(GL_TRIANGLES, 0, 3);
    
        glDisableVertexAttribArray(0);
    
        glutSwapBuffers();
    }
    
    
    static void InitializeGlutCallbacks()
    {
        glutDisplayFunc(RenderSceneCB);
        glutIdleFunc(RenderSceneCB);
    }
    
    static void CreateVertexBuffer()
    {
        Vector3f Vertices[3];
        Vertices[0] = Vector3f(-1.0f, -1.0f, 0.0f);
        Vertices[1] = Vector3f(1.0f, -1.0f, 0.0f);
        Vertices[2] = Vector3f(0.0f, 1.0f, 0.0f);
    
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
    }
    
    static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
    {
        GLuint ShaderObj = glCreateShader(ShaderType);
    
        if (ShaderObj == 0) {
            fprintf(stderr, "Error creating shader type %d\n", ShaderType);
            exit(1);
        }
    
        const GLchar* p[1];
        p[0] = pShaderText;
        GLint Lengths[1];
        Lengths[0]= strlen(pShaderText);
        glShaderSource(ShaderObj, 1, p, Lengths);
        glCompileShader(ShaderObj);
        GLint success;
        glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
        if (!success) {
            GLchar InfoLog[1024];
            glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
            fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
            exit(1);
        }
    
        glAttachShader(ShaderProgram, ShaderObj);
    }
    
    static void CompileShaders()
    {
        GLuint ShaderProgram = glCreateProgram();
    
        if (ShaderProgram == 0) {
            fprintf(stderr, "Error creating shader program\n");
            exit(1);
        }
    
        string vs, fs;
    
        if (!ReadFile(pVSFileName, vs)) {
            exit(1);
        };
    
        if (!ReadFile(pFSFileName, fs)) {
            exit(1);
        };
    
        AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
        AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);
    
        GLint Success = 0;
        GLchar ErrorLog[1024] = { 0 };
    
        glLinkProgram(ShaderProgram);
        glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
        if (Success == 0) {
            glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
            fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
            exit(1);
        }
    
        glValidateProgram(ShaderProgram);
        glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
        if (!Success) {
            glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
            fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
            exit(1);
        }
    
        glUseProgram(ShaderProgram);
    
        gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
        assert(gWorldLocation != 0xFFFFFFFF);
    }
    
    int main(int argc, char** argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
        glutInitWindowSize(1024, 768);
        glutInitWindowPosition(100, 100);
        glutCreateWindow("Tutorial 06");
    
        InitializeGlutCallbacks();
    
        // Must be done after glut is initialized!
        GLenum res = glewInit();
        if (res != GLEW_OK) {
          fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
          return 1;
        }
    
        printf("GL version: %s\n", glGetString(GL_VERSION));
    
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    
        CreateVertexBuffer();
    
        CompileShaders();
    
        glutMainLoop();
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172

    顶点着色器shader.vs代码修改如下:

    
    #version 330
    
    layout (location = 0) in vec3 Position;
    
    // 平移变换聚矩阵一致变量
    uniform mat4 gWorld;
    
    void main()
    {
        // 用平移变换矩阵乘以图形顶点位置对应的4X4矩阵相乘,完成平移变换
        gl_Position = gWorld * vec4(Position, 1.0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    片断着色器shader.fs脚本代码不变:

    
    #version 330
    
    out vec4 FragColor;
    
    void main()
    {
        FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    运行效果:

    红色三角形在X轴上左右来回移动。

    这里写图片描述
    这里写图片描述sx341125

    • 2017-04-17 10:
    展开全文
  • MATLAB--数字图像处理 图像平移

    万次阅读 多人点赞 2019-09-07 16:08:37
    图像平移 对于图像的平移,MATLAB中是可以利用膨胀函数平移图像。 代码: I = imread('a1.jpg'); se = translate(strel(1), [50 140]);%将一个平面结构化元素分别向下和向右移动30个位置 J = imdilate(I,se);%利用...

    图像平移

    对于图像的平移,MATLAB中是可以利用膨胀函数平移图像。
    代码:

    I = imread('a1.jpg');
    se = translate(strel(1), [50 140]);%将一个平面结构化元素分别向下和向右移动30个位置
    J = imdilate(I,se);%利用膨胀函数平移图像
    subplot(121);imshow(I), title('原图')
    subplot(122), imshow(J), title('移动后的图像');
    

    效果图:
    在这里插入图片描述
    这里我重点说平移的基本原理及代码实现。

    首先,我们必须要知道图像是怎么平移的?图像可以看成二维矩阵,由很多的像素点组成,假设一个像素点的坐标为(1,2),我们向下平移2个像素,向右平移3个像素,那么目标坐标就是(3,5)。这个在二维坐标中很好得出结果,无非就是横纵坐标加减偏移地址罢了,但是在矩阵中怎么算呢?其实这里有几种方法,但思维都是一样的。看原理:
    假设(x0,y0)是原图像的点,Tx是x方向偏移量,Ty是y方向偏移量(图像处理一般向下为x轴,向右为y轴)。那么(x1,y1)可以由下图矩阵计算。

    在这里插入图片描述
    通过上面的矩阵运算,我们对原图像的中的每一个像素点进行该变换(仅仅是位置变换),得到新的坐标,然后在新坐标下显示原图像。

    代码(这个是copy别人的,她用的矩阵变换和我的不一样,但是原理相同):

    I=rgb2gray(imread('a1.jpg'));%读入图片并转化为灰度图
    subplot(1,2,1),imshow(I),title('原图');                   %建立窗口,显示灰度图I
    [r,c]=size(I);                      %计算灰度图的大小,r表示行,c表示列,即通过size函数将灰度图I的行数存在矩阵的r中,列数存在矩阵的c中,这样就知道灰度图的大小是r×c
    dst=zeros(r,c);                     %建立r×c的0矩阵(平移结果矩阵),初始化为零(黑色)
    dx=50;                              %平移的x方向的距离,这里是竖直方向
    dy=80;                              %平移的y方向的距离,这里是水平方向
    tras=[1 0 dx;0 1 dy;0 0 1];         %平移变换矩阵
    for i=1:r
        for j=1:c
            temp=[i;j;1];               %灰度图I要平移变换的点,这里用矩阵表示
            temp=tras*temp;             %矩阵相乘,得到三行一列的矩阵temp,即平移后的矩阵
            x=temp(1,1);                %把矩阵temp的第一行第一列的元素给x   
            y=temp(2,1);                %把矩阵temp的第二行第一列的元素给y 
            if(x>=1&&x<=r)&&(y>=1&&y<=c)%判断所变换后得到的点是否越界
                dst(x,y)=I(i,j);        %得到平移结果矩阵,点(x,y)是由点(i,j)平移而来的,有对应关系 
            end
        end
    end
    subplot(1,2,2),imshow(uint8(dst)),title('平移后');          %建立窗口,显示平移后的图
    

    效果图:
    在这里插入图片描述
    效果虽然达到了,但是,她的这种写法好像都变成了灰色图片。那么怎么得到和膨胀函数的效果一样呢?
    这个也简单,我们只需要对原图像的三个通道分别平移,再合成就ok了(就是这么简单,哈哈)。
    代码(这个才是我写的):

     t=imread('a1.jpg');
    
    %分别提取三通道的矩阵
    t_1=t(:,:,1)
    t_2=t(:,:,2)
    t_3=t(:,:,3)
    
    %这里不能是[m,n]=size(t),我们是用三个二维矩阵合成一个三维图片(这里图片看出三维,毕竟有RGB)
    [m,n,z]=size(t);
    
    % 定义偏移量
    dx=50;
    dy=140;
    
    %定义新矩阵 ,存储新坐标
    r_1=zeros(m,n);
    r_2=zeros(m,n);
    r_3=zeros(m,n);
    
    %martix 变换用的矩阵
    martix=[1,0,dx;0,1,dy;0,0,1];
    
    %坐标变换
    for i=1:m
    for j=1:n
    tem=[i;j;1];
    tem=martix*tem;
    x=tem(1,1);
    y=tem(2,1);
    if(x>=1&&x<=m)&&(y>=1&&y<=n)
    r_1(x,y)=t_1(i,j);
    r_2(x,y)=t_2(i,j);
    r_3(x,y)=t_3(i,j);
    end
    end
    end
    
    %得到三个新矩阵合成一张图片
    rt=t
    rt(:,:,1)=r_1;
    rt(:,:,2)=r_2;
    rt(:,:,3)=r_3;
    
    %显示
    subplot(1,2,1),imshow(t),title('原图');
    subplot(1,2,2),imshow(rt),title('平移后');
    

    效果图:
    在这里插入图片描述

    更多

    获取更多资料、代码,微信公众号:海轰Pro
    回复 海轰 即可

    展开全文
  • 图像处理 - 图像平移

    千次阅读 2016-08-05 17:52:21
    初始坐标为(x0,y0)的点经过平移(tx,ty)(以向右,向下为正方向)后,坐标变为(x1,y1)。这两点之间的关系是x1=x0+tx ,y1=y0+ty。 以矩阵的形式表示为: 逆变换:  我们想知道的是平移后的图象中每个...

    初始坐标为(x0,y0)的点经过平移(tx,ty)(以向右,向下为正方向)后,坐标变为(x1,y1)。这两点之间的关系是x1=x0+tx y1=y0+ty


    以矩阵的形式表示为:

    逆变换:


      我们想知道的是平移后的图象中每个象素的颜色。例如我们想知道,新图中左上角点的RGB值是多少?很显然,该点是原图的某点经过平移后得到的,这两点的颜色肯定是一样的,所以只要知道了原图那点的RGB值即可。那么到底新图中的左上角点对应原图中的哪一点呢?将左上角点的坐标(0,0)入公式(2.2),得到x0=-tx y0=-ty;所以新图中的(0,0)点的颜色和原图中(-tx , -ty)的一样。

    如果你用过Photoshop,Corel PhotoPaint等图象处理软件,可能听说过“灰度图”(grayscale)这个词。灰度图是指只含亮度信息,不含色彩信息的图象,就象我们平时看到的黑白照片:亮度由暗到明,变化是连续的。因此,要表示灰度图,就需要把亮度值进行量化。通常划分成0255256个级别,其中0最暗(全黑)255最亮(全白).bmp格式的文件中,并没有灰度图这个概念,但是,我们可以很容易在.bmp文件中表示灰度图。方法是用256色的调色板,只不过这个调色板有点特殊,每一项的RGB值都是相同的。也就是说RGB值从(000)(111)一直到(255255255)(000)是全黑色,(255255255)是全白色,中间的是灰色。这样,灰度图就可以用256色图来表示了。为什么会这样呢?难道是一种巧合?其实并不是。

    在表示颜色的方法中,除了RGB外,还有一种叫YUV的表示方法,应用也很多。电视信号中用的就是一种类似于YUV的颜色表示方法。

    在这种表示方法中,Y分量的物理含义就是亮度,UV分量代表了色差信号(你不必了解什么是色差,只要知道有这么一个概念就可以了)。使用这种表示方法有很多好处,最主要的有两点:

    (1)    因为Y代表了亮度,所以Y分量包含了灰度图的所有信息,只用Y分量就能完全能够表示出一幅灰度图来。当同时考虑UV分量时,就能够表示出彩色信息来。这样,用同一种表示方法可以很方便的在灰度和彩色图之间切换,而RGB表示方法就做不到这一点了。

    (2)    人眼对于亮度信号非常敏感,而对色差信号的敏感程度相对较弱。也就是说,图象的主要信息包含在Y分量中。这就提示我们:如果在对YUV信号进行量化时,可以“偏心”一点,让Y的量化级别多一些(谁让它重要呢?)而让UV的量化级别少一些,就可以实现图象信息的压缩。这一点将在第9章介绍图象压缩时仔细研究,这里就不深入讨论了。而RGB的表示方法就做不到这一点,因为RGB三个分量同等重要,缺了谁也不行。YUVRGB之间有着如下的对应关系


    先看x方向(width指图象的宽度)

    (1)    tx-width:很显然,图象完全移出了屏幕,不用做任何处理;

    (2)    -width<tx0容易看出,图象区域的x范围从0width-|tx|,对应原图的范围从|tx|width

    (3)    0< tx <width:如图2.6所示。容易看出,图象区域的x范围从txwidth,对应原图的范围从0width - tx

    (4)    txwidth:很显然,图象完全移出了屏幕,不用做任何处理。

    y方向是对应的(height表示图象的高度)

    (1)    ty-height,图象完全移出了屏幕,不用做任何处理;

    (2)    -height<ty0,图象区域的y范围从0height-|ty|,对应原图的范围从|ty|height

    (3)    0<ty<height ,图象区域的y范围从tyheight,对应原图的范围从0height-ty

    (4)    tyheight,图象完全移出了屏幕,不用做任何处理。

    这种做法利用了位图存储的连续性,即同一行的象素在内存中是相邻的。利用memcpy函数,从(x0,y0)点开始,一次可以拷贝一整行(宽度为x1x0),然后将内存指针移到(x0,y0+1)处,拷贝下一行。这样拷贝(y1-y0)行就完成了全部操作,避免了一个一个象素的计算,提高了效率。下面将会贴上代码,编译环境是VC 6.0 (单文档程序)。

    首先还是先打开图像,这里需要加个类,表示x方向和y方向平移。

    Doc.h:

    class CMyDoc : public CDocument
    {
    public:
    	BITMAPFILEHEADER m_file;
    	BITMAPINFOHEADER m_info;
    	BITMAPINFO* bmpinfo;
    
    	BYTE *bmpdata;
    	BOOL isOpen;
    Doc.cpp:

    CMyDoc::CMyDoc()
    {
    	// TODO: add one-time construction code here
    	isOpen=FALSE;
    	bmpinfo=NULL;
    	bmpdata=NULL;
    }
    View.cpp:

    void CMyView::OnDraw(CDC* pDC)
    {
    	CMyDoc* pDoc = GetDocument();
    	ASSERT_VALID(pDoc);
    	// TODO: add draw code for native data here
    	BYTE* pData = NULL;
    	pData = pDoc->bmpdata;
    	
    	if(pDoc->isOpen == TRUE)
    	{
    		SetDIBitsToDevice(//12个参数
    			pDC->m_hDC, //设备环境句柄
    			0,//绘制目标矩形区域的左上角x坐标
    			0,//绘制目标矩形区域的左上角y坐标
    			pDoc->bmpinfo->bmiHeader.biWidth,//绘制目标矩形区域的宽度width
    			pDoc->bmpinfo->bmiHeader.biHeight,//绘制目标矩形区域的高度height
    			0,//位图区域的左下角x坐标
    			0,//位图区域的左下角y坐标
    			0,//显示图片的起始行
    			pDoc->bmpinfo->bmiHeader.biHeight,//扫描总行数
    			pData,//位图数据起首地址
    			pDoc->bmpinfo,//位图信息头首地址
    			DIB_RGB_COLORS//颜色参数
    			);
    	}
    }
    void CMyView::OnPingyi() 
    {
    	// TODO: Add your command handler code here
    	CMyDoc* pc=GetDocument();
    	CPingyi dlg;
    	dlg.SetDocument(pc);
    	dlg.DoModal();
    	Invalidate();
    }
     CPingYi是新加的类,用来记录x方向和y方向。

    Pingyi.h:

    #if !defined(AFX_PINGYI_H__304A149B_64E3_4480_ACB5_D3AF19143F29__INCLUDED_)
    #define AFX_PINGYI_H__304A149B_64E3_4480_ACB5_D3AF19143F29__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    // Pingyi.h : header file
    //
    #include "平移Doc.h"
    /
    // CPingyi dialog
    
    class CPingyi : public CDialog
    {
    public:
    	int GetX();//获取对话框里的x数据
    	int GetY();//获取对话框里的Y数据
    
    	int m_x;
    	int m_y;
    
        CMyDoc*poc;
    	void SetDocument(CMyDoc *m);
    	CMyDoc* GetDocument();
    
    	void Move(BYTE *bmpdata,int width,int height,int xx,int yy);
    // Construction
    public:
    	CPingyi(CWnd* pParent = NULL);   // standard constructor
    
    // Dialog Data
    	//{{AFX_DATA(CPingyi)
    	enum { IDD = IDD_MOVE };
    		// NOTE: the ClassWizard will add data members here
    	//}}AFX_DATA
    
    
    // Overrides
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CPingyi)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL
    
    // Implementation
    protected:
    
    	// Generated message map functions
    	//{{AFX_MSG(CPingyi)
    	afx_msg void OnChangeEdit1();
    	afx_msg void OnChangeEdit2();
    	virtual void OnOK();
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    //{{AFX_INSERT_LOCATION}}
    // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    
    #endif // !defined(AFX_PINGYI_H__304A149B_64E3_4480_ACB5_D3AF19143F29__INCLUDED_)
    
    Pingyi.cpp:

    // Pingyi.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "平移.h"
    #include "Pingyi.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /
    // CPingyi dialog
    
    
    CPingyi::CPingyi(CWnd* pParent /*=NULL*/)
    	: CDialog(CPingyi::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CPingyi)
    		// NOTE: the ClassWizard will add member initialization here
    	//}}AFX_DATA_INIT
    }
    
    
    void CPingyi::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CPingyi)
    		// NOTE: the ClassWizard will add DDX and DDV calls here
    	//}}AFX_DATA_MAP
    }
    
    
    BEGIN_MESSAGE_MAP(CPingyi, CDialog)
    	//{{AFX_MSG_MAP(CPingyi)
    	ON_EN_CHANGE(IDC_EDIT1, OnChangeEdit1)
    	ON_EN_CHANGE(IDC_EDIT2, OnChangeEdit2)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /
    // CPingyi message handlers
    
    void CPingyi::OnChangeEdit1() 
    {
    	// TODO: If this is a RICHEDIT control, the control will not
    	// send this notification unless you override the CDialog::OnInitDialog()
    	// function and call CRichEditCtrl().SetEventMask()
    	// with the ENM_CHANGE flag ORed into the mask.
    	m_x=GetDlgItemInt(IDC_EDIT1);
    	// TODO: Add your control notification handler code here	
    }
    
    void CPingyi::OnChangeEdit2() 
    {
    	// TODO: If this is a RICHEDIT control, the control will not
    	// send this notification unless you override the CDialog::OnInitDialog()
    	// function and call CRichEditCtrl().SetEventMask()
    	// with the ENM_CHANGE flag ORed into the mask.
    	m_y=GetDlgItemInt(IDC_EDIT2);
    	// TODO: Add your control notification handler code here
    	
    }
    
    int CPingyi::GetX()
    {
    	return m_x;
    }
    
    int CPingyi::GetY()
    {
    	return m_y;
    }
    
    void CPingyi::OnOK() 
    {
    	// TODO: Add extra validation here
    	Move(GetDocument()->bmpdata,GetDocument()->m_info.biWidth,GetDocument()->m_info.biHeight,GetX(),GetY());
    	CDialog::OnOK();
    }
    
    void CPingyi::SetDocument(CMyDoc *m)
    {
    	poc=m;
    }
    
    CMyDoc* CPingyi::GetDocument()
    {
    	return poc;
    }
    
    void CPingyi::Move(BYTE *bmpdata,int width,int height,int xx,int yy)
    {
    	BYTE *data;//;临时的存储空间
    	BYTE *yuan;//原来的数据地址
    	BYTE *bian;//改变后的图像地址
    
    	int x1,y1;//原来的坐标
    
    	int x2,y2;//平移后的坐标
    
    	LONG zijie;//字节
        zijie = WIDTHBYTES(width * 8);
        data=(BYTE *)new BYTE[zijie*height];
    	if(!data) delete[] data;
    	
    	for(x2=0;x2<height;x2++)
    		for(y2=0;y2<width;y2++)
    		{
    			bian=data+zijie*(height-1-x2)+y2;
    			
    			x1= x2 - yy;
    			y1= y2 - xx;
    			if((x1>0)&&(x1<height)&&(y1>0)&&(y1<width))
    			{
    				yuan=bmpdata+zijie*(height-1-x1)+y1;
    
    				*bian=*yuan;				
    			}
    			else
    				* ((unsigned char*)bian) = 125;
    		}
         memcpy(bmpdata,data,zijie*height);
    	 delete [] data;
    
    }
    展开全文
  • C语言实现bmp图像的平移操作

    千次阅读 2014-07-31 19:50:52
    在编程中,先将处理后图像的所有区域赋值为白色,然后找出平移后显示区域的左上角点(x0,y0)和右下角点(x1,y1),分以下几种情况处理: 先看x方向(width为图像的宽度) (1)t (2)-width (3)0 (4)t>=wi
  • 图像几何变换又叫做图像基本变换,主要包括图像平移、图像缩放和图像旋转个部分,当然还有图像镜像等简单的内容。图像基本变换是图像处理的基本内容,是学习以后复杂的仿射变换、透视变换以及更高级的MLS网格变形...
  • Opencv之图像平移、镜像

    千次阅读 2016-09-12 14:27:17
    图像的平移、旋转、镜像都是图像处理的基本功,按理说我现在研究它,有点晚了,但我还是抽些时间写下吧,弥补过去的... 下面介绍几种方法来实现图像的平移 1.自己用暴力青年.data写的 #include #include using n
  • 在我们读计算机视觉的相关论文时,经常会看到平移不变性这个词,通常观点中,大家都是普遍认为CNN是具有平移不变性的,然而近年来,一些工作的研究对平移不变性提出了质疑,本文对一些平移不变性的理解进行记录,...
  • 属性动画实现平移效果

    千次阅读 2016-06-29 20:57:07
    View Animation相当简单,不过只能支持简单的缩放、平移、旋转、透明度基本的动画,且一定的局限性。比如:你希望View一个颜色的切换动画;你希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的...
  • 在Verilog中实现一个去除直流的模块,其中输入的数据,分两路: 一路进入4096的延迟连,进行延迟; 另一路进入4096点的求和,右移除以4096的取平均值模块; 最后将延迟后的输入点,减去均值,即为去除直流后的值...
  • 卷积层提取的特征具有平移不变性

    千次阅读 2020-10-02 17:25:00
    不变性以下几种类型: 平移不变性;旋转不变性;尺度不变性;光照不变性。 对于图像分类任务: 平移不变性就是图像中的目标不管被移动到哪个位置,模型给出的标签都是相同的。 除此之外,还有一个对应的概念:平移...
  • Android属性动画 - 平移动画

    千次阅读 2019-09-22 11:52:15
    补间动画的其他动画实现方式很类似,能够将一个掌握透彻,其他也就迎刃而解,本篇文章主要讲解属性动画-平移动画的具体实现,同时也会概况属性动画的其他几种类型,相信看完本篇文章会对属性动画一个全面的认识。...
  • 【VTK】平面的平移和旋转

    千次阅读 2018-11-04 11:23:07
    本文探讨的平面操作主要是平移和绕轴旋转。 在vtkPlane中保存数据成员 double Normal[3]; double Origin[3]; 同时,vtkPlane也提供了原点读写函数,法向量读写函数 /** * Set/get point through which ...
  • 旋转变换和平移变换

    千次阅读 2017-04-21 16:22:04
    1、刚性变换:平移变换+狭义旋转变换,共6个自由度 2、广义旋转变换:绕任意一个旋转轴旋转一定的角度,广义旋转变换 = 刚性变换 广义旋转变换 = 狭义旋转变换(3个自由度)+ 平移变换(3个自由度) 广义旋转变换...
  • 例:MainActivity 主方法类:public class MainActivity extends AppCompatActivity implements View.OnClickListener { ...//平移 private Button mxz;//旋转 private Button mjb;//渐变 priva...
  • 【Android】超简单!打造一个任意View缩放平移工具

    千次阅读 多人点赞 2018-06-04 19:13:47
    打造一个任意View缩放平移工具 话说坚持写博客是真的难,不过确实收获,这段时间又忙成狗了,最近事不多,还是要把这个坚持下去的。 公司的一个项目需要给自定义控件加上缩放平移功能,前人写的代码之写了...
  • 在WebGL中,如果我们想实现更高级的动态场景,或者是对物体进行坐标变换,那么旋转、平移和缩放必不可少。这些变换所涉及的是一些矩阵运算,先从二维平面讲起,再推导至三维空间。下面分别对这几种变换进行一个讲解...
  • 利用TranslateAnimation 动画实现上下平移横线 用TranslateAnimation 动画实现上下平移横线。 利用TranslateAnimation 动画实现上下平移横线,实现了类似动态扫描框里面的感觉,其主要的设定过程如下。 首先在需要...
  • 卷积网络的平移不变性可能会经常在论文中看到,那这个到底是什么呢?看了一些论文的原文和...所以不变性下面几种平移不变性:Translation Invariance 旋转不变性:Rotation Invariance 尺度不变性:scale Inva
  • 本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程《数字图像处理》及课件进行讲解,主要通过MFC单文档视图实现显示BMP图片空间几何变换,包括图像平移、图形旋转、图像反转倒置镜像和图像...
  • 如何使用 SVG 进行缩放和平移

    万次阅读 2013-01-07 17:48:44
    本主题演示了如何使用可缩放的向量图形 (SVG) 进行缩放和平移,并在结尾处提供了一个可进行缩放和平移的复杂组织结构图示例。假定你掌握了基本的 HTML 和 JavaScript 知识,并能访问可在 HTML5 中呈现内联 SVG 的...
  • 【一步步学OpenGL 6】 -《平移变换》

    千次阅读 2016-09-15 00:29:19
    教程6:平移变换原文: http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html背景从这个教程开始我们开始研究各种各样的图形变换,图形变换就可以让一个3d物体在屏幕中变换的的时候看上去保持深度的错觉,...
  • 本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程《数字图像处理》及课件进行讲解,主要通过MFC单文档视图实现显示BMP图片空间几何变换,包括图像平移、图形旋转、图像反转倒置镜像和图像...
  • 首先推荐一下鸿洋大大的打造个性的图片预览与多点触控视频教程,这套教程教我们一步一步实现了多点触控实现对图片的平移和缩放的功能,这篇文章我将在鸿洋大大的基础之上做了一些扩展功能: 1.图片的惯性滑动 2....
  • 数字图像处理的主要两方法:空域法和频域法  图像变换主要两重要方式:图像几何...概念:图像平移是指将图像中所有像素点按照指定的平移量水平或垂直移动到期望的位置。图像平移只是改变图像在屏幕上的位置,图像
  • 解析几何--对称,平移和旋转

    千次阅读 2019-02-27 23:17:19
    平移和旋转时解析几何中常用的坐标变换方法。坐标变换可能出现在问题中,也可能出现在解题的过程中。 解题时,通过巧妙的平移旋转,可以简化计算,使题目变得更加直观,方便解题。 例如,对于对称图形,只需要计算...
  • Android单点触控技术,对图片进行平移,缩放,旋转操作 相信大家使用多点对图片进行缩放,平移的操作很熟悉了,大部分大图的浏览都具有此功能,有些app还可以对图片进行旋转操作,QQ的大图浏览就可以对图片进行...
  • CNN 平移不变性尺度不变性 绝对位置

    千次阅读 2020-04-01 11:42:16
    CNN是否存在平移和尺度的不变性和相等性 ref https://zhuanlan.zhihu.com/p/113443895 论文:How much position information do convolutional neural networks encode? 图中一共三组图片,每组由原图和剪切图构成...
  • 二次函数是中学时代要学习的基本函数之一,在学习的时候要掌握它的平移规律,在黑板上演示函数的平移存在缺陷,不能让学生们直观感受,所以可以制作平移动画进行演示,下面来学习具体制作技巧。 在二次函数学习中,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 111,300
精华内容 44,520
关键字:

平移有几种