2018-10-29 18:45:30 lgyuWT 阅读数 1250

选定的图像,图形或物体,对待处理的图像进行遮挡,来控制图像处理的区域或处理过程。用于覆盖特定图像或物体称为掩模或模板。光学图像处理中,掩模可以做胶片、滤光片等。数字图像处理中,掩模为二维矩阵数组,有时也用多值图像。

数字图像处理中,图像掩模主要用于:

  1. 提取感兴趣区,用预先制作的感兴趣区掩模与待处理图想相乘,得到感兴趣图像,感兴趣内图像值保持不变,而区外图像值都为0.
  2. 屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数计算,或进队屏蔽区做处理统计。
  3. 结构特征提取,用相似性变量或图像匹配方法检测和图像中与淹没相似的结构特征。
  4. 特殊形状图像的制作。用选定的图像、图形或物体,对待处理的图像进行遮挡,来控制图像处理的区域或处理过程。用于覆盖特定的特定图像或物体称为掩模或模板。

掩模是一种图像滤波的模板,实用掩模经常处理的是遥控图像。当提取道路或者河流,或者房屋时,通过一个n*n的矩阵来对图像进行像素过滤,然后将我们需要的地物或者标志突出显示出来。这个矩阵就是一种掩模。

2019-10-26 17:34:40 wujuxKkoolerter 阅读数 147

梯形高通滤波

梯形高通滤波器(TLPF)的传递函数如下:

$$
H(u,v) = 1 - \begin{cases}
1 & D(u,v) \lt D_0 \\
\frac{D(u,v) - D_1}{D_0-D_1} & D_0 \lt D(u,v) \leq D_1 \\
0 &D(u,v) > D_1
\end{cases}

\tag{18-1}

$$

Python语言实现的代码如下:

def trapezoidal_low_pass_kernel(img,D0=5,D1=10):
    assert img.ndim == 2
    r,c = img.shape[1],img.shape[0]
    u = np.arange(r)
    v = np.arange(c)
    u, v = np.meshgrid(u, v)
    low_pass = np.sqrt( (u-r/2)**2 + (v-c/2)**2 )

    idx = low_pass < D0
    idx2 = (low_pass >= D0) & (low_pass <= D1)
    idx3 = low_pass > D1

    low_pass[idx] = 1
    low_pass[idx2] = (low_pass[idx2] - D1) / (D1 - D0)
    low_pass[idx3] = 0

    return low_pass

def trapezoidal_high_pass_filter(img,D0=5,D1=15):
    assert img.ndim == 2
    gray = np.float64(img)
    kernel = 1 - trapezoidal_low_pass_kernel(img,D0,D1)
    gray_fft = np.fft.fft2(gray)
    gray_fftshift = np.fft.fftshift(gray_fft)
    dst = np.zeros_like(gray_fftshift)
    dst_filtered = kernel * gray_fftshift
    dst_ifftshift = np.fft.ifftshift(dst_filtered)
    dst_ifft = np.fft.ifft2(dst_ifftshift)
    dst = np.abs(np.real(dst_ifft))
    dst = np.clip(dst,0,255)
    return np.uint8(dst)

程序运行结果:

在这里插入图片描述

2019-10-24 22:10:00 wujuxKkoolerter 阅读数 91

梯形低通滤波器

梯形低通滤波器(TLPF)的传递函数如下:

H(u,v)={1D(u,v)<D0D(u,v)D1D0D1D0<D(u,v)D10D(u,v)>D1(10-1) H(u,v) = \begin{cases} 1 & D(u,v) \lt D_0 \\\\ \frac{D(u,v) - D_1}{D_0-D_1} & D_0 \lt D(u,v) \leq D_1 \\\\ 0 &D(u,v) > D_1 \end{cases} \tag{10-1}

其中,D0D_0称为梯形低通滤波器的截止频率。D0D_0D1D_1按要求指定D0<D1D_0 < D_1,它的性能介于理想低通滤波与巴特沃斯低通滤波器之间,对图像具有一定的模糊和振铃效应。

在这里插入图片描述

Python语言实现代码如下:

def trapezoidal_low_pass_kernel(img,D0=5,D1=10):
    assert img.ndim == 2
    r,c = img.shape[1],img.shape[0]
    u = np.arange(r)
    v = np.arange(c)
    u, v = np.meshgrid(u, v)
    low_pass = np.sqrt( (u-r/2)**2 + (v-c/2)**2 )

    idx = low_pass < D0
    idx2 = (low_pass >= D0) & (low_pass <= D1)
    idx3 = low_pass > D1

    low_pass[idx] = 1
    low_pass[idx2] = (low_pass[idx2] - D1) / (D1 - D0)
    low_pass[idx3] = 0

    return low_pass

def trapezoidal_low_pass_filter(img,D0=5,D1=15):
    assert img.ndim == 2
    gray = np.float64(img)
    kernel = trapezoidal_low_pass_kernel(img,D0,D1)
    gray_fft = np.fft.fft2(gray)
    gray_fftshift = np.fft.fftshift(gray_fft)
    dst = np.zeros_like(gray_fftshift)
    dst_filtered = kernel * gray_fftshift
    dst_ifftshift = np.fft.ifftshift(dst_filtered)
    dst_ifft = np.fft.ifft2(dst_ifftshift)
    dst = np.abs(np.real(dst_ifft))
    dst = np.clip(dst,0,255)
    return np.uint8(dst)

程序运行结果
在这里插入图片描述

2010-09-22 22:31:00 xingyu19871124 阅读数 13276

数字图像处理的课题报告打算做个图像畸变校正方向的,忙了几天把matlab仿真程序做出来了,下一步使用VC来实现这个过程!

这里先把程序贴出来以备后用!

梯形畸变的校正流程:直方图均衡---》垂直边缘检测----》开操作---》radon变换求极值---》求检测直线---》取点---》校正

matlab代码如下:

clc ;%清屏
clear all ;%清内存

%读取原图像
img=imread('大楼1.bmp') ;

%转化为灰度图像
img_gray=rgb2gray(img) ;
figure(1) ;
imshow(img_gray) ;
title('Gray Image') ;

%直方图均衡
img_histeq=histeq(img_gray) ;
figure(2) ;
imshow(img_histeq,[]) ;
title('Histgram Equalization Image') ;
%sobel边缘检测
%  img_sobel=edge(img_histeq,'sobel') ;
img_sobel=sobel(img_histeq) ;
figure(3) ;
imshow(img_sobel,[]) ;
title('Sobel Edge Detection ') ;
kernel=[1;1;1;1;1;1;1;1] ;
img_erode=imerode(img_sobel,kernel) ;
img_dilate=imdilate(img_erode,kernel) ;
figure(4)
imshow(img_dilate) ;
title('Dilate Image') ;
%radon检测直线
theta = 0:179;
[R,xp] = radon(img_dilate,theta);
figure(5) ;
imagesc(theta, xp, R); colormap(hot);
xlabel('/theta (degrees)'); ylabel('x/prime');
title('R_{/theta} (x/prime)');
colorbar

%计算直线 注意radon变换的圆心在图像的中心
gray_max1=max(max(R(:,1:90))) ;
gray_max2=max(max(R(:,90:180))) ;
[len1,theta1]=find(R==gray_max1) ;
[len2,theta2]=find(R==gray_max2) ;
theta1=theta1+90-1 ;
theta2=theta2-90-1 ;
len1=len1-length(R)/2 ;
len2=len2-length(R)/2;
%斜率
k1=-cot(theta1*pi/180) ;%注意前面要带负号,因为y朝下
k2=-cot(theta2*pi/180) ;

%求原点到直线的垂足的坐标
[m,n]=size(img_dilate) ;
x1=n/2+len1*sin(theta1*pi/180);
y1=m/2-len1*cos(theta1*pi/180);
x2=n/2-len2*sin(theta2*pi/180);
y2=m/2-len2*cos(theta2*pi/180);

%在图像中画线,标出检测出来的直线,直线方程为x-x0=k(y-y0) ;
y1_1=0 ;
x1_1=k1*(y1_1-y1)+x1 ;
y1_2=m ;
x1_2=k1*(y1_2-y1)+x1 ;

y2_1=0 ;
x2_1=k2*(y2_1-y2)+x2 ;
y2_2=m ;
x2_2=k2*(y2_2-y2)+x2 ;
figure(4) ;
hold on ;
% line('xdata', [left right], 'ydata', [top bottom])
%标注垂足
markpoint(x2,y2,'g') ;
markpoint(x1,y1,'g') ;
%将检测出来的直线画出来
line([x1_1,x1_2],[y1_1,y1_2]) ;
line([x2_1,x2_2],[y2_1,y2_2]) ;


%寻找四个连接点
y11=m*3/4 ;
x11=k1*(y11-y1)+x1 ;
y111=m/4 ;
x111=x11 ;
x11_1=k1*(y111-y1)+x1 ;
y21=y11 ;
x21=k2*(y21-y2)+x2 ;
y211=y111 ;
x211=x21 ;
x21_1=k2*(y211-y2)+x2 ;

markpoint(x11,y11,'g') ;
markpoint(x111,y111,'g') ;
markpoint(x11_1,y111,'r') ;
markpoint(x21,y21,'g') ;
markpoint(x211,y211,'g') ;
markpoint(x21_1,y211,'r') ;
%校正
basepoints=[x11 y11;x21 y21;x111,y111;x211,y211] ;
inputpoints=[x11 y11;x21 y21;x11_1,y111;x21_1,y211] ;
cpt=cp2tform(inputpoints,basepoints,'projective') ;
figure(6) ;
img_correction=imtransform(img,cpt) ;
imshow(img_correction);
title('Distortion Correction Image') ;

 

%标点函数

function markpoint(x,y,color)
line([x-5,x+5],[y,y],'Color',color) ;
line([x,x],[y-5,y+5],'Color',color) ;

%垂直边缘检测函数,不是sobel边缘检测

function img_sobel=sobel(img_test)
[m,n]=size(img_test) ;
img_sobel=zeros(m,n) ;
alpha=2 ;
for i=2:m-1
    for j=2:n-1
        temp=uint16(abs(int16(img_test(i-1,j-1))+alpha*int16(img_test(i,j-1))+int16(img_test(i+1,j-1))-int16(img_test(i-1,j+1))-alpha*int16(img_test(i,j+1))-int16(img_test(i+1,j+1)))) ;
        if(temp>125)
            temp=255 ;
        else
            temp=0 ;
        end
        img_sobel(i,j)=uint8(temp) ;
    end
end
return ;

2016-06-26 12:08:51 baixiaozhe 阅读数 8527

摄像头观察一个矩形的图片时往往只能得到一个扭曲的图片:

原图:


实际情况是摄像头经常从某个角度观察图片:

 

使用opencv的透视变换把图片矫正为正视的角度,大概过程:

1、通过灰度、模糊和二值化得到:


2、然后对查找图片外包矩形轮廓,并查找角点得到:


3、通过梯形四个角点和外包矩形的四个顶点得到变换矩阵,进行投射变换,最后得到:


如果图片看不到,请来 http://blog.csdn.net/baixiaozhe/article/details/51762086

代码如下:

//图片投射变换
-(void)wrapImg{
    UIImage *imageInView  = [UIImage imageNamed:@"wrap"];
    Mat wrapSrc;
    //默认转为4通道 所以下面Scalar也得是4通道,否则不能正确实现颜色
    UIImageToMat(imageInView, wrapSrc);
     NSLog(@"wrapSrc cols%d rows%d channels%d type%d depth%d elemSize%zu",wrapSrc.cols,wrapSrc.rows,wrapSrc.channels(),wrapSrc.type(),wrapSrc.depth(),wrapSrc.elemSize());
 
     //灰度
    Mat graymat;
    cvtColor(wrapSrc ,graymat,COLOR_BGR2GRAY);
     blur(graymat, graymat, Size2d(7,7));
     //二值化,灰度大于14的为白色 需要多调整 直至出现白色大梯形
    graymat=graymat>14;
    
     //Shi-Tomasi 角点算法参数
    int maxCorners=4;
    vector<Point2f> corners;
    double qualityLevel=0.01;
    double minDistance=100;//角点之间最小距离
    int blockSize=7;//轮廓越明显,取值越大
    bool useHarrisDetector=false;
    double k=0.04;
     //Shi-Tomasi 角点检测
    goodFeaturesToTrack(graymat,corners,maxCorners,qualityLevel,minDistance,Mat(),blockSize,useHarrisDetector,k);
     //cout<<"检测到角点数:"<<corners.size()<<endl;
    NSLog(@"检测到角点数:%lu",corners.size());
    int r=10;
    RNG rng;
    //画出来看看 找到的是不是四个顶点 另外角点检测出来的点顺序每次不一定相同
    /*
    if(corners.size()==4){
        circle(wrapSrc,corners[0],r,Scalar(255,0,0,255),2,8,0);//红
        circle(wrapSrc,corners[1],r,Scalar(0,255,0,255),2,8,0);//绿
        circle(wrapSrc,corners[2],r,Scalar(0,0,255,255),2,8,0);//蓝
        circle(wrapSrc,corners[3],r,Scalar(255,255,0,255),2,8,0);//黄
    }
      _imageView.image= MatToUIImage(wrapSrc) ;
     return;
    */
    std::vector<std::vector<cv::Point>> contoursOutLine;
    findContours(graymat,contoursOutLine,CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE);
    // 对轮廓计算其凸包//
    // 边界框
    cv::Rect boudRect;
    vector<Point2i>  poly ;
    for( int i = 0; i < contoursOutLine.size();  i++)
    {
        // 边界框
        boudRect=  boundingRect(contoursOutLine[i] );
        //面积过滤
        int tmpArea=boudRect.area();
        if(tmpArea>= 50000 )
        {
            rectangle(wrapSrc,cvPoint(boudRect.x,boudRect.y),cvPoint(boudRect.br().x ,boudRect.br().y ),Scalar(128),2);
        }
    }
     //src=wrapSrc(boudRect); 用这种方式截屏有时候会出错 不知咋回事
    //用IOS的 quartz api来截图
     UIImage *image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect([imageInView CGImage], CGRectMake(boudRect.x,boudRect.y,boudRect.width,boudRect.height))];
     Mat src,warp_dst;
    UIImageToMat(image, src);
 
    
     warp_dst = Mat::zeros( src.rows, src.cols, src.type() );
    
    //从梯形srcTri[4] 变换成 外包矩形dstTri[4]
    Point2f srcTri[4];
    Point2f dstTri[4];
   
    Point2f aRect1=boudRect.tl();
     // 梯形四个顶点 顺序为 左上  右上  左下  右下
    Point2f srcTri0 = Point2f(corners[0].x-aRect1.x  ,corners[0].y-aRect1.y );
    Point2f srcTri1 = Point2f(corners[2].x-aRect1.x  ,corners[2].y-aRect1.y );
    Point2f srcTri2 = Point2f(corners[1].x-aRect1.x  , corners[1].y-aRect1.y );
    Point2f srcTri3 = Point2f(corners[3].x-aRect1.x  , corners[3].y-aRect1.y );
    //查找左上点 取出外包矩形的中点,然后把梯形四个顶点与中点进行大小比较,如x,y都小于中点的是左上,x大于中点,y小于中点 则为右上
    Point2f boudRectCenter=Point2f(src.cols/2,src.rows/2);
    if(srcTri0.x>boudRectCenter.x){
        if(srcTri0.y>boudRectCenter.y){//右下
            srcTri[3]=srcTri0;
        }else{//右上
            srcTri[1]=srcTri0;
        }
    }else{
        if(srcTri0.y>boudRectCenter.y){//左下
          srcTri[2]=srcTri0;
        }else{//左上
            srcTri[0]=srcTri0;
        }
    }
    if(srcTri1.x>boudRectCenter.x){
        if(srcTri1.y>boudRectCenter.y){//右下
            srcTri[3]=srcTri1;
        }else{//右上
            srcTri[1]=srcTri1;
        }
    }else{
        if(srcTri1.y>boudRectCenter.y){//左下
            srcTri[2]=srcTri1;
        }else{//左上
            srcTri[0]=srcTri1;
        }
    }

    if(srcTri2.x>boudRectCenter.x){
        if(srcTri2.y>boudRectCenter.y){//右下
            srcTri[3]=srcTri2;
        }else{//右上
            srcTri[1]=srcTri2;
        }
    }else{
        if(srcTri2.y>boudRectCenter.y){//左下
            srcTri[2]=srcTri2;
        }else{//左上
            srcTri[0]=srcTri2;
        }
    }

    if(srcTri3.x>boudRectCenter.x){
        if(srcTri3.y>boudRectCenter.y){//右下
            srcTri[3]=srcTri3;
        }else{//右上
            srcTri[1]=srcTri3;
        }
    }else{
        if(srcTri3.y>boudRectCenter.y){//左下
            srcTri[2]=srcTri3;
        }else{//左上
            srcTri[0]=srcTri3;
        }
    }
      // 画出来 看看顺序对不对
    circle(src,srcTri[0],r,Scalar(255,0,0,255),-1,8,0);//红 左上
    circle(src,srcTri[1],r,Scalar(0,255,0,255),-1,8,0);//绿 右上
    circle(src,srcTri[2],r,Scalar(0,0,255,255),-1,8,0);//蓝 左下
    circle(src,srcTri[3],r,Scalar(255,255,0,255),-1,8,0);//黄 右下
    
     _imageView.image= MatToUIImage(src) ;
     //  return;
    
    // 外包矩形的四个顶点, 顺序为 左上  右上  左下  右下
    dstTri[0] = Point2f( 0,0 );
    dstTri[1] = Point2f( src.cols - 1, 0 );
    dstTri[2] = Point2f( 0, src.rows - 1 );
    dstTri[3] = Point2f( src.cols - 1, src.rows - 1 );
    //自由变换 透视变换矩阵3*3
    Mat warp_matrix( 3, 3, CV_32FC1 );
    warp_matrix=getPerspectiveTransform(srcTri  ,dstTri  );
    warpPerspective( src, warp_dst, warp_matrix, warp_dst.size(),WARP_FILL_OUTLIERS);
    
     _imageView.image= MatToUIImage(warp_dst) ;
 }

_imageView是图片控件的插头

梯形

阅读数 92

没有更多推荐了,返回首页