剛開會每週的例會,最討厭開會了,不過爲了能順利畢業,只能忍了。閒話不多說了,下面把上週學習的一個簡單的算法總結一下,以備後面寫畢業論文的時候可以參考一下。
一、Census Transform(CT)算法的學習
123 |
127 |
129 |
126 |
128 |
129 |
127 |
131 |
130 |
然後比較此窗口中每個像素值(中心除外)與中心像素值的大小,如果比中心像素值小,則比較結果爲1,否則爲0。由此,得到如下結果:
然後,把此窗口結果組成一個序列: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的核(至於爲什麼這麼說,可以看看前面提到的那篇論文)。如此來計算的話,則前面例子產生的結果窗口應該爲:
對應的二進制序列爲: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;
-
double tempvalue = cvGetReal2D(&window, w, h);
-
if(tempvalue < m.val[0] + delta)
-
census += 1;
-
}
-
}
-
cvSetReal2D(modified_image, i, j, census);
-
}
-
}
-
-
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!