`
wangleide414
  • 浏览: 606921 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

Matlab矢量化编程技巧

 
阅读更多

 

级别:★

经常看到一些Matlab初学者写出带有层层循环的代码,这些代码往往运行得很慢,而且非常难懂。Matlab提供了大量的命令来避免循环

建议是:在确定要写一个针对矩阵操作的2重循环之前,请仔细阅读帮助中的Maximizing MATLAB Performance一节。

里面有很多例子,这里举一个我自己碰到的问题:

要统计数字图像的亮度最大值和最小值,由于数字图像可能是一个二维或三维的矩阵,开始我写出了如下的代码:

switch ndims(img)

case 2

m = max(max(img));

case 3

m = max(max(max(img)));

end

后来对这种做法很不满意,如果有一个8维的矩阵,难道我要写

max(max(max(max(max(max(max(max(x))))))))

才行?后来发现无论矩阵是什么维数,实际上

max( x(:) )

就够了。

点评:y = x(:) 这种方式可以返回矩阵的所有元素,形成一个列向量 y,无视 x 的维数。注:y 对 x 以列优先的方式排列

 

 

级别:★★★

问题:提取一幅RGB图象中的蓝色部分

解答:

[Copy to clipboard] [ - ]
CODE:
A=imread('input.bmp');
H = size(A);
BB=repmat(255, H(1)*H(2), H(3));
C=(A(:,:,1)==0 & A(:,:,2)==0 & A(:,:,3)==255);
BB(C,1) = 0;
BB(C,2) = 0;
B = reshape(BB, H(1), H(2), H(3));
imwrite(B,'output.bmp');


点评:注意 repmat 和 reshape 的用法。解答的关键是对 reshape 命令的灵活使用,把三维矩阵转换为二维矩阵,从而使得求出满足条件的下标矩阵 C 可以对原矩阵 A 进行引用。否则,这类问题一定摆脱不了循环语句。

 

级别:★

问题:赋值的技巧——当矩阵很多元素是相同时(下面以0为例,且不考虑稀疏矩阵的存储方式),“先生成全零阵,后再对特殊元素赋值”的方式将有利于缩短运行的时间。

例如:

把矩阵 A 作 0 扩展(变身:1个变4个,原来真身维持不变,其他假身为0),l例如:
A =
     1     2     3     4
    -1    -2    -3    -4
     0     4     2     9

希望得到:

B=
     1     2     3     4     0     0     0     0
    -1    -2    -3    -4     0     0     0     0
     0     4     2     9     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0

解答:

[Copy to clipboard] [ - ]
CODE:

B = repmat(zeros(size(A)), 2, 2);
B(1:size(A,1), 1:size(A,2)) = A;


不推荐的做法:

[Copy to clipboard] [ - ]
CODE:

[row, col] = size(A);
for i = 1:2*row
  for j = 1:2*col
    if i >=1 && i <= row && j >= 1 && j <= col
      B(i, j) = A(i, j);
    else
      B(i, j) = 0;
  end
end


点评:也许是受制于 C 语言的影响,初学者往往把 matlab 当作 C 语言来使用,加上 matlab 宣称变量不需要定义即可以直接使用,因此导致大量的循环+单变量判断语句。掌握“:”运算符是向 matlab 矢量化编码进军的必经之路。

 

 

级别:★★

问题:有个80*80的矩阵,如何去掉全为0的行或者列

解答:

[Copy to clipboard] [ - ]
CODE:

a =
     0     0     0    -3     0
     1     0     0     0     0
     0     2     0     0     0
     0     0     0     0     0
     0     0     0     0     0

>> a(:,~sum(abs(a),1))=[]
a =
     0     0    -3
     1     0     0
     0     2     0
     0     0     0
     0     0     0

>> a(~sum(abs(a),2),:)=[]
a =
     0     0    -3
     1     0     0
     0     2     0


点评:又是一个摆脱循环思想的典型例子。除了“: ”运算符的妙用之外,逻辑法对矩阵的下标索引也相当重要。此外,线性代数的知识也在这里得到体现:|a|+|b|+|c|=0 当且仅当 a = b = c = 0

 

 

级别:★★★★★


问题:对一幅灰度图像求它的二维联合分布密度——假设不使用 matlab 自带的函数直接求出来(如果有的话)

问题详细描述:

QUOTE:

设 (i,j), (k,l) 两个任意象素点上的灰度值分别为 g(i,j) 和 g(k,l),其值分别假设为 a, b,则图像灰度值的联合分布密度表示为
P(a,b)=Pk{g(i,j)=a, g(k,l)=b},其中 a, b 均为 0 到 L-1 之间的灰度整量电平。
由于灰度图象是 unint8 型,那它的灰度级就是 256 个灰度级。根据上面关于二维联合分布密度的定义,即是要求得到这幅图中同时满足某个给定条件的点的数量,这个条件是两个位置上像素的灰度值与当前统计的灰度配对是一致的。整个二维联合分布密度矩阵与协方差矩阵类似。


常规解答:

[m,n]=size(a);
a1=0
for ii=1:256
    for jj=1:256
        I0(ii,jj)=0;
        for i=1:m
            for j=1:n
                for k=1:m
                    for l=1:n
                        if (a(i,j)==(ii-1))&(a(k,l)==(jj-1))
                            I0(ii,jj)=I0(ii,jj)+1;
                            a1=a1+1;
                        end
                    end
                end
            end
        end
    end
end;


简短说明:程序中的 ii, jj 即是相关的 a, b 值,它可以为 0 到 255 之间的任意数(也可以理解为用 ii 作为横坐标, jj 作为纵坐标)。设置了 a, b 的值后,就用个 FOR 循环来寻找图象中任两个位置上能够同时满足像素值为 a 和像素值为 b 的点(即为 IF 语句后的条件),当满足条件时,那么在该点上加一,就能统计出同时满足 a, b 的点的数量。因为 a, b 可以取不同的值,那么就能得出一个 256*256 大小的矩阵,也就是想要的二维联合分布密度。

优化解答:


A = [1,2,3;2,3,6;6,4,5;1,1,3];
B = unique(A);
C = hist(double(A(:)), double(length(B)));
D = C'*C;
E = -diag(diag(D))+D;
E = diag(C) + E;
A
E


点评:这是 matlab 编程思想转变的一个典型例子,即从算法上去改进程序,使之减少循环。常规解法使用了6个循环,而优化解法则没有使用循环。转化的思想是:考虑到问题本身的特点,即:灰度配对的点的个数(简称点数) = 各灰度点数之积,因此首先求出矩阵 A 中互异的元素 B,然后,利用 hist 函数统计每个互异元素出现的次数 C,即各灰度点数。在此基础上,C 的转置与 C 的乘积矩阵 D 就是两互异灰度的点数。剩下的问题是把 D 的主对角线换掉(因为相乘时统计多了),这通过先置零,后添加来进行。

 

 级别:★

问题:求出满足特定条件的元素,并按行统计个数

解答:

不推荐的做法:

[Copy to clipboard] [ - ]
CODE:
[m,n]=size(t2);
for j=1:n
  for i=1:m
    if (t2(i,j)-y2(i,j))/t2(i,j)<0.2
        hege(j)=hege(j)+1;
    end
  end
end


推荐的做法:

[Copy to clipboard] [ - ]
CODE:
A = ((t2-y2)./t2) < 0.2;
hege = sum(A,1);


点评:充分发挥 matlab 基于矩阵的思想,从整体出发考虑问题,避免了使用基于 C 语言 的循环语句。

 

级别:★★★★★

问题:游程平滑算法:将连续的且个数小于某个阈值的0全部替换成1,例如:

平滑前:1111100000111100011
平滑后:1111100000111111111

解答:

常规解法:

[Copy to clipboard] [ - ]
CODE:
clear all
I=[0 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 0 0 0 1];
T = 4;
Idiff = diff(I);
index1 = find(Idiff == -1);
index2 = find(Idiff == 1);
if length(index1) == 0 | length(index2) == 0,
    %%%全1或者全0的情况,根据自己需要单独处理一下
    coutinue;
else
    if length(index1) == length(index2)+1,
        tt = index2 - index1(1:end-1);
        tt = [tt,length(I)-index1(end)];
        index3 = find(tt <= T);
        for ii = 1:length(index3);
            I(index1(index3(ii))+1:index1(index3(ii))+tt(index3(ii))) = 1;
        end
    elseif length(index1) == length(index2)-1,
        if index2(1) <= T;
            I(1:index2(1)) = 1;
        end
        tt = [index2(2:end) - index1];
        index3 = find(tt <= T);
        for ii = 1:length(index3);
            I(index1(index3(ii))+1:index1(index3(ii))+tt(index3(ii))) = 1;
        end
    elseif length(index1) == length(index2),
        if index1(1)>index2(1),
            if index2(1) <= T;
                I(1:index2(1)) = 1;
            end
            tt = index2(2:end) - index1(1:end-1);
            index3 = find(tt <= T);
            for ii = 1:length(index3);
                I(index1(index3(ii))+1:index1(index3(ii))+tt(index3(ii))) = 1;
            end
            if length(I)-index1(end) <=T,
                I(index1(end):end) = 1;
            end
        elseif index1(1) < index2(1),
            tt = index2 - index1;
            index3 = find(tt <= T);
            for ii = 1:length(index3);
                I(index1(index3(ii))+1:index1(index3(ii))+tt(index3(ii))) = 1;
            end
        end
    end
end
I


优化解法:

[Copy to clipboard] [ - ]
CODE:
a = [1 0 0 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1];
T = 4;
b = sprintf('%d',a);
[c,d]=regexp(b,'0+');   %%%
ind = find(d - c < T);
for ii = 1:length(ind),
    a(c(ind(ii)):d(ind(ii))) = 1;
end
a


点评:优化解法巧妙地运用了正则表达式这个工具来处理特定字符串的搜索、匹配问题,因此比较快捷、简便。正则表达式的应用非常广泛,它是一种可以用于模式匹配和替换的强有力的工具。其作用如下:
1) 测试字符串的某个模式。例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证;
2) 替换文本。可以在文档中使用一个正则表达式来标识特定文字,然后可以全部将其删除,或者替换为别的文字。

备注:能否使用 regexpreg 命令一次性地进行搜索并完成替代呢?这样也许可以摆脱最后的循环语句。可惜本人功力有限,暂时未能实现。
分享到:
评论

相关推荐

    MATLAB向量化编程基础精讲 有书签 高清扫描版 + 源代码

    不能免费就要1个币吧,好书分享!读读这个对matlab编程水平有提高!MATLAB向量化编程基础精讲 马良,祁彬彬 有书签 ...还逐一展开了延伸分析,使学习 MATLAB 编程的用户,能迅速体会 MATLAB 矢量化编程语言的基本特色。

    MATLAB向量化编程基础精讲 马良,祁彬彬 有书签 高清扫描版 【附源代码】

    最低价!MATLAB向量化编程基础精讲 马良,祁彬彬 有书签 高清扫描版 附源代码!。本书拣选 MathWorks 官方群组 Cody...还逐一展开了延伸分析,使学习 MATLAB 编程的用户,能迅速体会 MATLAB 矢量化编程语言的基本特色。

    matlab代码矢量化指南

    在MATLAB编程中,矢量化是一种优化代码性能的...总之,理解并运用MATLAB的矢量化编程,对于提升代码效率和编写更加优雅的MATLAB代码至关重要。通过不断学习和实践,开发者可以更好地驾驭这种强大的工具,提高工作效率。

    matlab高效编程技巧

    - **矢量化编程**:重新审视并深入理解MATLAB中的矢量化编程技术。这一技术能够显著提高代码的运行效率,尤其是在处理大规模数据集时尤为重要。 - **处理海量数据的方法**:探讨如何有效地在MATLAB中处理大量数据,...

    MATLAB编程技巧详解.docx

    MATLAB 编程技巧详解 ...本文介绍了六个常用的 MATLAB 编程技巧,包括向量化编程、矢量化计算、使用结构体、函数句柄、并行计算和调试与性能优化。掌握这些技巧对于提高 MATLAB 编程效率和代码质量非常重要。

    精通matlab7.0混合编程.

    2.8.1 矢量化操作 2.8.2 给数组预定义维 2.8.3 下标或者索引操作 2.8.4 尽量多使用函数文件而少使用非脚本文件 2.8.5 将循环体中的内容转换为c-mex 2.8.6 内存优化 2.9 小结 第3章 matlab混合编程简介 3.1 进行混合...

    Matlab高效编程25个案例分析

    内容包括:MATLAB快速入门、重新认识矢量(向量)化编程、MATLAB处理海量数据、匿名函数类型介绍、嵌套函数类型介绍、积分以及积分方程求解案例、优化及非线性方程(组)求解案例、人脸图像压缩与重建案例、有关预测...

    MATLAB.rar_矢量化_矢量量化_量化

    3. **向量化与数组函数**:讨论arrayfun、cellfun、numel、size等函数如何帮助我们进行矢量化编程。 4. **数组索引和切片**:介绍如何利用索引和切片技巧,如线性索引、逻辑索引和花式索引,实现复杂的数据选择和...

    《MATLAB高效编程技巧与应用:25个案例分析》.docx

    2. **矢量(向量)化编程**:介绍MATLAB的核心编程思想,如何利用向量化编程提高代码效率,避免循环,提升计算速度。 3. **处理海量数据**:讲解MATLAB在大数据处理中的策略和技巧,包括数据存储、内存管理以及并行...

    MATLAB索引代码矢量化指南

    在MATLAB编程中,索引和引用是基本操作,用于选取矩阵中的子集。这篇《MATLAB代码矢量化指南》详细介绍了三种基本的索引...通过代码矢量化,可以显著提升计算性能,避免不必要的循环,实现更符合MATLAB本质的编程风格。

    Matlab编程技巧与实例分析.docx

    在Matlab中,向量化操作是一种重要的编程技巧。通过将循环操作转换为矢量操作,可以大大提高代码的效率。例如,假设我们有一个包含10000个元素的向量x,我们想将其中大于0的元素设置为1,小于0的元素设置为-1,可以...

    《MATLAB高效编程技巧与应用:25个案例分析》.pdf

    2. **矢量(向量)化编程**:MATLAB以矩阵运算为基础,向量化的编程方式可以显著提升代码运行速度。书中详细讨论了新旧版本中向量化编程的异同,指导读者如何避免不必要的循环,利用内建函数实现高效计算。 3. **...

    matlab编程思想

    ### MATLAB编程思想:代码矢量化指南 #### 一、基本技术 **1. MATLAB索引或引用** 在MATLAB中,索引或引用是处理数据结构的重要方式之一,特别是对于矩阵来说更是如此。掌握MATLAB的索引机制有助于更高效地操作...

    matlab开发-solarazimuthandlevation估算的全矢量化

    四、MATLAB编程技巧 1. 时间和日期处理:MATLAB提供了datetime类,可以方便地处理日期和时间,用于计算太阳位置。 2. 矢量化计算:通过向量化操作,避免了传统的循环结构,显著提升计算效率。 3. 数组广播:MATLAB的...

    MATLAB开发环境使用技巧.docx

    3. **优化技巧**:MATLAB的性能优化包括矢量化计算和预分配矩阵空间。矢量化计算通过矩阵或向量操作替换循环,减少计算时间;预分配矩阵空间则在循环开始前分配固定大小,避免了矩阵大小动态调整带来的性能损失。 4...

    第四章程序:一维配点型无网格法MATLAB程序.zip_-baijiahao_matlab一维网格_无网格法MATLAB编程_无

    通过对这些源代码的学习和理解,读者可以深入掌握无网格法的基本原理和MATLAB编程技巧,为进一步研究二维或三维问题打下基础。 总的来说,一维配点型无网格法MATLAB程序是数值计算领域的重要实践,它结合了数学模型...

    MATLAB技术程序设计技巧.docx

    在优化过程中,可以使用矢量化和并行计算技术,进一步提高程序的执行效率。 五、错误处理和异常处理 在编写 MATLAB 程序时,需要考虑各种异常情况的处理方式。MATLAB 提供了异常处理机制,可以捕获并处理程序中...

    VC与Labview、Matlab编程论文资料[2].rar

    这是VC与Labview、Matlab编程论文资料,全部为pdf格式,讲述有VC编程技巧、也有VC与Labview混合编程, VC与matlab混合编程,有365个,约500M,分成4个【独立】压缩包,如果想要全部的论文则需要下载全部压 缩包,...

    新建文件夹 (2)_matlab_圆极化_电磁波圆极化matlab仿真_

    在MATLAB平台上进行圆极化电磁波仿真是一个复杂但有趣的过程,这涉及到对电磁波的基本理论理解以及MATLAB编程技巧。圆极化电磁波是电磁波的一种特殊形式,其电场矢量按照顺时针或逆时针方向旋转,形成一种周期性的极...

    分享一些matlab源代码-matlab.zip

    此外,MATLAB还支持向量化和矢量化编程,这可以大大提高代码的运行效率。 在信号处理方面,代码可能包含滤波器设计、频谱分析、时频分析等算法。例如,使用fft函数进行快速傅里叶变换,或使用fir1和iir1函数设计...

Global site tag (gtag.js) - Google Analytics