关于统计变换(CT/MCT/RMCT)算法的学习和实现

原文地址http://blog.sina.com.cn/s/blog_684c8d630100turx.html

刚开会每周的例会,最讨厌开会了,不过为了能顺利毕业,只能忍了。闲话不多说了,下面把上周学习的一个简单的算法总结一下,以备后面写毕业论文的时候可以参考一下。
一、Census Transform(CT)算法的学习
    Census Transform 算法是Ramin Zabih 和 John Woodfill 于1994年在他们的论文 《Non-parametric LocalTransforms for Computing VisualCorrespondence》中提出的,正如他们在论文中所说,这是一种非参数变换,主要用来表征图像的局部结构特征,能够比较好的检测到图像中的边缘特征和角点特征,从这篇论文的470次的引用次数来看,CT算法用处还是挺广泛的。下面简要介绍一下CT算法的基本思想:用一个3*3或者5*5的滑动窗口遍历整幅图像,对于每次遍历的位置,以3*3为例,假设某个位置如下图所示

123127129
126128129
127131130

然后比较此窗口中每个像素值(中心除外)与中心像素值的大小,如果比中心像素值小,则比较结果为1,否则为0。由此,得到如下结果:

110
1 0
100

然后,把此窗口结果组成一个序列:11010100,以此二进制序列表示的值来代替原图像窗口中心点的像素。如此下去,等到窗口滑动完整幅图像,我们就得到原图像做统计变换(CT)之后的图像。

注意:只能作用于灰度图像,对于彩色图像,则需要转换为灰度图之后再操作;为了简单起见,我没有考虑图像的边缘像素值。
   下面给出一种用 matlab 实现的版本:
% *************************************************************************
% Title: Function-Census Transform of a given Image
% Author: Siddhant Ahuja
% Created: May 2008
% Copyright Siddhant Ahuja, 2008
% Inputs: Image (var: inputImage), Window size assuming square window (var:
% windowSize) of 3x3 or 5x5 only.
% Outputs: Census Tranformed Image (var: censusTransformedImage),
% Time taken (var: timeTaken)
% Example Usage of Function: [a,b]=funcCensusOneImage('Img.png', 3)
% *************************************************************************
function [censusTransformedImage, timeTaken] = funcCensusOneImage(inputImage, windowSize)
% Grab the image information (metadata) using the function imfinfo
try
imageInfo = imfinfo(inputImage);
% Since Census Transform is applied on a grayscale image, determine if the
% input image is already in grayscale or color
if(getfield(imageInfo,'ColorType')=='truecolor')
% Read an image using imread function, convert from RGB color space to
% grayscale using rgb2gray function and assign it to variable inputImage
inputImage=rgb2gray(imread(inputImage));
else if(getfield(imageInfo,'ColorType')=='grayscale')
% If the image is already in grayscale, then just read it.       
inputImage=imread(inputImage);
else
error('The Color Type of Input Image is not acceptable. Acceptable color types are truecolor or grayscale.');
end
end
catch
inputImage = inputImage;
end
% Find the size (columns and rows) of the image and assign the rows to
% variable nr, and columns to variable nc
[nr,nc] = size(inputImage);
% Check the size of window to see if it is an odd number.
if (mod(windowSize,2)==0)
error('The window size must be an odd number.');
end
if (windowSize==3)
bits=uint8(0);
% Create an image of size nr and nc, fill it with zeros and assign
% it to variable censusTransformedImage of type uint8
censusTransformedImage=uint8(zeros(nr,nc));
else if (windowSize==5)
bits=uint32(0);
% Create an image of size nr and nc, fill it with zeros and assign
% it to variable censusTransformedImage of type uint32       
censusTransformedImage=uint32(zeros(nr,nc));
else
error('The size of the window is not acceptable. Just 3x3 and 5x5 windows are acceptable.');
end
end
% Initialize the timer to calculate the time consumed.
tic;
% Find out how many rows and columns are to the left/right/up/down of the
% central pixel
C= (windowSize-1)/2;
for j=C+1:1:nc-C % Go through all the columns in an image (minus C at the borders)
for i=C+1:1:nr-C % Go through all the rows in an image (minus C at the borders) 
census = 0; % Initialize default census to 0
for a=-C:1:C % Within the square window, go through all the rows
for b=-C:1:C % Within the square window, go through all the columns
if (~(a==0 && b==0)) % Exclude the centre pixel from the calculation,原来是(C+1),现改为0
census=bitshift(census,1); %Shift the bits to the left  by 1
% If the intensity of the neighboring pixel is less than
% that of the central pixel, then add one to the bit
% string
if (inputImage(i+a,j+b) < inputImage(i,j))
census=census+1;
end
end
end
end
% Assign the census bit string value to the pixel in imgTemp
censusTransformedImage(i,j) = census;
end
end
% Stop the timer to calculate the time consumed.
timeTaken=toc;
   这是我在网上找到的一个实现的版本,注释比较多,除去注释的话,真正代码没有50行,比较简单,相信大家都可以看的懂。
  之前讲了CT算法的实现,下面说一下 MCT 以及 RMCT的实现。

二、Modified Census Transform (MCT)算法
    MCT 算法是 CT 算法的一个修改版本,它是由Bernhard Froba 在做人脸检测的时候提出来的,在他2004年发表的论文《Face Detection with theModified Census Transform》中,Bernhard Froba将 CT算法中“滑动窗口中每个像素值与中心位置像素做比较”改为“滑动窗口中每个像素值与整个窗口中像素的均值做比较”,这样,原有的每个3*3的窗口可能产生256种序列(因为没有算中心像素),现在变为可能产生512种序列(其实全0和全1的序列表示的是同样的信息,可以排除一个),也就是做完MCT之后,图像的每个像素值的范围为0——511,这样就能够比较充分的利用3*3的核(至于为什么这么说,可以看看前面提到的那篇论文)。如此来计算的话,则前面例子产生的结果窗口应该为:
110
100
100

对应的二进制序列为:110100100。然后以此作为中心像素点的像素值,循环完毕之后便得到MCT之后的图像。需要注意的一点是,如果要使变换之后的图像得到显示,应该对像素值做一下归一化,使其在0——255之间。

三、Revised Modified Census Transform (RMCT)算法
    RMCT 算法其实又是对 MCT的又一次修改,它与 MCT的不同之处仅仅在于一个微小的△m,即:在滑动窗口像素均值上加上一个微小的变量△m=1或者2。其他都是完全一样的。

    下面附上这两种修改版统计变换的 C++代码,代码是我自己编的,是基于VS2008和OpenCV2.0的,仅供参考:
#include "stdafx.h" 
#include "MCT.h" 
#include "highgui.h" 
 
MCT::MCT() 
{ 
    window_size = 0; 
} 
 
MCT::~MCT() 
{ 
} 
 
void MCT::ModifiedCensusTransform(IplImage *input_image, IplImage *mct_image, const int window_size, const int delta ) 
{ 
    CvSize image_size = cvGetSize(input_image); 
    int image_width = image_size.width; 
    int image_height = image_size.height; 
 
    IplImage *gray_image = cvCreateImage(cvGetSize(input_image), input_image->depth, 1); 
    cvSetZero(gray_image); 
 
    if(input_image->nChannels != 1) 
    { 
        cvCvtColor(input_image, gray_image, CV_RGB2GRAY); 
    } 
    else 
    { 
        cvCopy(input_image, gray_image); 
    } 
 
 
    IplImage *modified_image = NULL; 
    switch (window_size) 
    { 
    case 3: 
        modified_image = cvCreateImage(image_size, IPL_DEPTH_16U, 1); 
        cvSetZero(modified_image); 
        break; 
    case 5: 
        modified_image = cvCreateImage(image_size, IPL_DEPTH_32S, 1); 
        cvSetZero(modified_image); 
        break; 
    default: 
        printf("window size must be 3 or 5!\n"); 
        exit(EXIT_FAILURE); 
    } 
 
    CvMat window; 
    for(int i = 0; i < image_height - window_size; i++) 
    { 
        for(int j = 0; j < image_width - window_size; j++) 
        { 
            unsigned long census = 0; 
            CvRect roi = cvRect(j, i, window_size, window_size); 
            cvGetSubRect(gray_image, &window, roi); 
            CvScalar m = cvAvg(&window, NULL); 
 
            for(int w = 0; w < window_size; w++) 
            { 
                for(int h = 0; h < window_size; h++) 
                { 
                    census = census << 1; //左移1位 
                    double tempvalue = cvGetReal2D(&window, w, h); 
                    if(tempvalue < m.val[0] + delta) 
                        census += 1; 
                } 
            } 
            cvSetReal2D(modified_image, i, j, census); 
        } 
    } 
    //cvConvertScaleAbs(modified_image, mct_image, 1, 0); 
    Normalize(modified_image, mct_image); 
    cvReleaseImage(&gray_image); 
    cvReleaseImage(&modified_image); 
} 
 
void MCT::Normalize(IplImage *mct_image, IplImage *nor_image) 
{ 
    double minv, maxv; 
    cvMinMaxLoc(mct_image, &minv, &maxv); 
    for (int i = 0; i < mct_image->height; i++) 
    { 
        for (int j = 0; j < mct_image->width; j++) 
        { 
            double tempv = cvGetReal2D(mct_image, i, j); 
            tempv = (tempv - minv) / (maxv - minv) * 255; 
            cvSetReal2D(nor_image, i, j, tempv); 
        } 
    } 
} 
由于算法比较简单,所以没有写注释,应该比较容易理解。
四、CT/MCT/RMCT的应用
    目前我读到的几篇论文里面,他们主要用于人脸检测或者面部伪装检测,用于做图像的预处理,这可能是因为CT算法对光照不敏感,可以比较好的排除光照对图像的影响。这里给出用到该算法的几篇paper:
1、《Face Detection with the Modified CensusTransform》(前面提到的那篇)
2、《Adaboost Based Disguised Face Discrimination on EmbeddedDevices》
3、《Disguised-Face Discriminator for Embedded Systems》

OVER!


  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值