zoukankan      html  css  js  c++  java
  • matlab练习程序(图像扭曲算法)

    方法就是先对图像按照cellsize设置网格,一般是16*16或32*32。

    然后对每个网格做投影变换,最后把所有格子拼起来就行了。

    单个格子类似下图:

    在实际编程的时候这里没有采用常见的反变换采样法,而是采用了正向变换的方式直接处理,投影公式见这里

    正向变换后得到待采样点集,再对点集重新进行一次栅格化,就能得到没有空洞的图像了。

    matlab代码如下:

    clear all;close all;clc;
    
    img=imread('lena.jpg');
    imshow(img)
    
    [h,w]=size(img);
    
    cellsize = 32;                              %网格大小,不同的大小会产生不同尺度的噪声
    G = rand(2,h/cellsize+1,w/cellsize+1)-0.5;  %每个网格顶点的随机方向向量
    G = G*8;                                    %方向向量乘上距离,扭曲大小
    
    pc = zeros(h*w,3);                          %扭曲后点集
    num=1;
    for y=1:cellsize:h-cellsize+1
        for x=1:cellsize:w-cellsize+1
            
            src = [x y;x y+cellsize-1; x+cellsize-1 y+cellsize-1;x+cellsize-1 y];           %扭曲前一个格子的四个坐标点
            
            indx = floor(x / cellsize) + 1;
            indy = floor(y / cellsize) + 1;
            
            dst = src + [G(:,indx,indy)';G(:,indx,indy+1)'; G(:,indx+1,indy+1)';G(:,indx+1,indy)']; %扭曲后一个格子的四个坐标点
            
            X = zeros(8,8);
            Y = zeros(8,1);                        
            X(1:4,1) = src(:,1);                        %计算投影矩阵
            X(1:4,2) = src(:,2);
            X(1:4,3) = 1;
            
            X(1:4,7) = -src(:,1).*dst(:,1);
            X(1:4,8) = -src(:,2).*dst(:,1);
            
            X(5:8,4) = src(:,1);
            X(5:8,5) = src(:,2);
            X(5:8,6) = 1;
            
            X(5:8,7) = -src(:,1).*dst(:,2);
            X(5:8,8) = -src(:,2).*dst(:,2);
            
            Y(1:4) = dst(:,1);
            Y(5:8) = dst(:,2);   
            A = inv(X)*Y;
            
            %得到扭曲后待采样点集
            for yy=y:y+cellsize-1
                for xx=x:x+cellsize-1          
                    x1 = (A(1)*xx+A(2)*yy+A(3)) / (A(7)*xx+A(8)*yy+1);
                    y1 = (A(4)*xx+A(5)*yy+A(6)) / (A(7)*xx+A(8)*yy+1);     
                    pc(num,:) = [x1 y1 double(img(xx,yy))];
                    num = num+1;
                end
            end     
        end
    end
    
    %点集投到一个较大的栅格(3*3)中,提升后续栅格化速度
    maxx = max(pc(:,1));
    minx = min(pc(:,1));
    maxy = max(pc(:,2));
    miny = min(pc(:,2));
    gridx = floor((maxx - minx)/3 )+ 1;
    gridy = floor((maxy - miny)/3 )+ 1;
    grid = cell(gridy,gridx);                  
    for i=1:length(pc)
        indx = floor((pc(i,1) - minx)/3) + 1;
        indy = floor((pc(i,2) - miny)/3) + 1;    
        grid{indy,indx} = [grid{indy,indx};pc(i,:)];
    end
    
    %对点集按(1*1)重新栅格化得到扭曲后图像
    imgre = zeros(h,w);
    for y=1:h
        for x=1:w
            indx = floor((x - minx)/3) + 1;
            indy = floor((y - miny)/3) + 1; 
    
            pctmp = [];        %在(3*3)*9格子中找最邻近点
            for dy = indy-1:indy+1
                for dx = indx-1:indx+1
                    if dx>=1 && dy>=1 && dx<=gridx && dy<=gridy
                        pctmp = [pctmp;grid{dy,dx}];
                    end
                end
            end
                
            if isempty(pctmp)==false
                d = [x y] - pctmp(:,1:2);
                [~,ind] = min(sqrt(d(:,1).^2+d(:,2).^2));
                imgre(y,x) = pctmp(ind,3);
            end
        end
    end
    
    figure;
    plot(pc(:,1),pc(:,2),'.')
    axis equal;
    
    figure;
    imshow(imgre',[])
    imwrite(uint8(imgre'),'imgre.jpg');
    
    %投到点云上看看
    figure;
    I=uint8(pc(:,3));   
    x=pc(:,1);
    y=pc(:,2);
    z=zeros(h*w,1);
    
    pcshow([x y z],[I I I]);    %如果是彩色图:pcshow([x y z],I);

    原图:

    扭曲结果:

    扭曲后点集(就是在该点集上栅格化):

    图像直接投到网格点云上:

    参考:http://www.360doc.com/content/06/0823/16/3500_188533.shtml

  • 相关阅读:
    HDU 4920 Matrix multiplication
    UVALive 5545 Glass Beads
    POJ 2230 Watchcow
    hdu 1878 欧拉回路
    hdu 3018 Ant Trip
    2015 Multi-University Training Contest 1 hdu 5296 Annoying problem
    深入理解php内核 编写扩展 I:介绍PHP和Zend
    PHP数组实际占用内存大小的分析
    深入理解php底层:php生命周期
    PHP实现的进度条效果详解
  • 原文地址:https://www.cnblogs.com/tiandsp/p/14389624.html
Copyright © 2011-2022 走看看