hog特征的matlab实现
%% 参数设置
blocksize=3; %⼀个block有2x2个cell
cellsize=32; %⼀个cell的⼤⼩为8像素x8像素
imgsize=[256 256];
overlap=true; %是否有重叠,重叠部分为50%,不可修改。
numbins=9;
%% 调⽤函数来传参
hog=thog(blocksize,cellsize,imgsize,overlap,numbins);
% Compute the expected window size (with 1 pixel border on all sides).
% hog.winSize = [(hog.numVertCells * llSize + 2), ...
% (hog.numHorizCells * llSize + 2)];
% %加2是因为当时取梯度的时候去除了边缘,现在加回去
% fprintf('Getting the HOG descriptor for an \n');
% Read in the pre-cropped (66 x 130) image.
%img = imread('./Images/Training/Positive/IMG_0009_x517_y326_w76_h177.png');
%% 读取maltab⾃带图⽚
img = imread('rice.png');
imshow(img);
img=imresize(img,hog.winSize);%缩放⾄这个⼤⼩,必须是hog.winSize,此时hog.winSize不等于imgsize [m,n]=size(img);
%% 调⽤函数来计算单张图⽚的hog特征
% Compute the HOG descriptor for this image.
H = getHOGDescriptor(hog, img);%hog是个结构体,有很多属性
注意,该代码调⽤了两个函数,所以需要将这两个函数也放在同⼀个⽂件夹中
thog.m
function hog=thog(blocksize,cellsize,imgsize,overlap,numbins)
% The number of bins to u in the histograms.
hog.numBins = numbins;%原论⽂⾥⾯就是9个通道效果最好
% Cell size in pixels (the cells are square).%cell的边长为8像素
%block的⼤⼩,边长为3个cell
hog.blockSize=blocksize;
hog.winSize=imgsize;%图⽚的⼤⼩
hog.overlap=overlap;%不重叠,重叠时重叠部分是50%
%将图⽚⼤⼩缩放⾄可以整除的范围
new_row = floor(hog.winSize(1)/llSize) * llSize;
new_col = floor(hog.winSize(2)/llSize) * llSize;
% new_img = imresize(img, [new_row new_col], 'bilinear');%以双线性插值来缩放
hog.winSize=[new_row+2 new_col+2];%更新hog.winSize
% The number of cells horizontally and vertically.
%cell的数量,⼀张图⽔平和竖直⽅向有多少个cell 130除以8=16.25(取整16)66除以8=8.25(取整8)% hog.numHorizCells = 8;
% hog.numVertCells = 16;
hog.numHorizCells =(hog.winSize(2)-2)/llSize;
hog.numVertCells = (hog.winSize(1)-2)/llSize;
end
getHOGDescriptor.m
function H = getHOGDescriptor(hog, img)
% GETHOGDESCRIPTOR computes a HOG descriptor vector for the supplied image.
% H = getHOGDescriptor(img)
%
% This function takes a 130 x 66 pixel gray scale image (128 x 64 with a
% 1-pixel border for computing the gradients at the edges) and computes a % HOG descriptor for the image, returning a 3,780 value column vector.
%
% Parameters:
% img - A grayscale image matrix with 130 rows and 66 columns.
% Returns:
% A column vector of length 3,780 containing the HOG descriptor.
%
% The intent of this function is to implement the same design choices as
% the original HOG descriptor for human detection by Dalal and Triggs.
% Specifically, I'm using the following parameter choices:
% - 8x8 pixel cells
% - Block size of 2x2 cells
% - 50% overlap between blocks
% - 9-bin histogram
%
% The above parameters give a final descriptor size of
% 7 blocks across x 15 blocks high x 4 cells per block x 9 bins per hist
% = 3,780 values in the final vector.
%
% A couple other important design decisions:
% - Each gradient vector splits its contribution proportionally between the
% two nearest bins
% - For the block normalization, I'm using L2 normalization.
%
% Differences with OpenCV implementation:
% - OpenCV us L2 hysteresis for the block normalization.
% - OpenCV weights each pixel in a block with a gaussian distribution
% before normalizing the block.
% - The quence of values produced by OpenCV does not match the order % of the values produced by this code.
% Empty vector to store computed descriptor.
H = [];
% Verify the input image size matches the HOG parameters.
% asrt(iqual(size(img), hog.winSize))
% ===============================
% Compute Gradient Vectors
% ===============================
% Compute the gradient vector at every pixel in the image.
% Create the operators for computing image derivative at every pixel.
hx = [-1,0,1];
hy = hx';
% Compute the derivative in the x and y direction for every pixel.
dx = filter2(hx, double(img));%就是滤波器为hx,然后把img滤波⼀下
dy = filter2(hy, double(img));
% Remove the 1 pixel border.
dx = dx(2 : (size(dx, 1) - 1), 2 : (size(dx, 2) - 1));
dy = dy(2 : (size(dy, 1) - 1), 2 : (size(dy, 2) - 1));
% Convert the gradient vectors to polar coordinates (angle and magnitude). angles = atan2(dy, dx);
magnit = ((dy.^2) + (dx.^2)).^.5;
% =================================
% Compute Cell Histograms
% =================================
% Compute the histogram for every cell in the image. We'll combine the cells % into blocks and normalize them later.
% Create a three dimensional matrix to hold the histogram for each cell.
histograms = zeros(hog.numVertCells, hog.numHorizCells, hog.numBins);
% For each cell in
for row = 0:(hog.numVertCells - 1)
% Compute the row number in the 'img' matrix corresponding to the top
% of the cells in this row. Add 1 since the matrices are indexed from 1.
rowOfft = (row * llSize) + 1;
% For each cell in
for col = 0:(hog.numHorizCells - 1)
% Select the pixels for this cell.
% Compute column number in the 'img' matrix corresponding to the left
% of the current cell. Add 1 since the matrices are indexed from 1.
colOfft = (col * llSize) + 1;
% Compute the indices of the pixels within this cell.
rowIndeces = rowOfft : (rowOfft + llSize - 1);
colIndeces = colOfft : (colOfft + llSize - 1);
% Select the angles and magnitudes for the pixels in this cell.
cellAngles = angles(rowIndeces, colIndeces);
cellMagnitudes = magnit(rowIndeces, colIndeces);
% Compute the histogram for this cell.
% Convert the cells to column vectors before passing them in.
histograms(row + 1, col + 1, :) = getHistogram(cellMagnitudes(:), cellAngles(:), hog.numBins);
end
end
% ===================================
% Block Normalization
% ===================================
% Take 2 x 2 blocks of cells and normalize the histograms within the block.
% Normalization provides some invariance to changes in contrast, which can
% be thought of as multiplying every pixel in the block by some coefficient.
% For each cell in
%for row = 1:(hog.numVertCells - 1) %循环次数要修改
if hog.overlap==1 %如果重叠,ps:那个除以2是因为重叠百分50,要是重叠25,就改成4,为了⽅便就不另外设参数了
k=0;
for row = 1:((hog.numVertCells - hog.blockSize)/floor((hog.blockSize/2))+1) %循环次数要修改,其实是这样的,(block=3x3,每次移动重叠50%) % For each cell in
%for col = 1:(hog.numHorizCells - 1) %循环次数要修改
for col = 1:((hog.numHorizCells-hog.blockSize)/floor((hog.blockSize/2)) +1) %循环次数要修改其实是这样的,(block=3x3,每次移动重叠50%) % Get the histograms for the cells in this block.
blockHists = histograms(row : row + hog.blockSize-1, col : col + hog.blockSize-1, :);
% Put all the histogram values into a single vector (nevermind the
% order), and compute the magnitude.
% Add a small amount to the magnitude to ensure that it's never 0.
magnitude = norm(blockHists(:)) + 0.01;
% Divide all of the histogram values by the magnitude to normalize
% them.
normalized = blockHists / magnitude;
% Append the normalized histograms to our descriptor vector.
H = [H; normalized(:)];
k=k+1;
end
end
% fprintf("v:%d, h:%d, k:%d",row,col,k);%⽤来排bug的,没什么实际⽤处
el%就是不重叠时,注意循环次数会改变,其他不变
for row = 1:(hog.numVertCells /hog.blockSize) %循环次数要修改,其实是这样的,(block=3x3,每次移动不重叠)
% For each cell in
%for col = 1:(hog.numHorizCells - 1) %循环次数要修改
for col = 1:(hog.numHorizCells/hog.blockSize) %循环次数要修改其实是这样的,(block=3x3,每次移动不重叠)
% Get the histograms for the cells in this block.
blockHists = histograms(row : row + hog.blockSize-1, col : col + hog.blockSize-1, :);
% Put all the histogram values into a single vector (nevermind the
% order), and compute the magnitude.
% Add a small amount to the magnitude to ensure that it's never 0.
magnitude = norm(blockHists(:)) + 0.01;
% Divide all of the histogram values by the magnitude to normalize
% them.
normalized = blockHists / magnitude;
% Append the normalized histograms to our descriptor vector.
H = [H; normalized(:)];
end
end
end
H = H';%转置为⾏向量
end
注意,这个getHOGDescriptor函数调⽤了其他的函数,因此也要将这个调⽤的这个函数放在⼀起,该函数如下getHistogram,m
function H = getHistogram(magnitudes, angles, numBins)
% GETHISTOGRAM Computes a histogram for the supplied gradient vectors.
% H = getHistogram(magnitudes, angles, numBins)
%
% This function takes the supplied gradient vectors and places them into a
% histogram with 'numBins' bad on their unsigned orientation.
%
% "Unsigned" orientation means that, for example, a vector with angle
% -3/4 * pi will be treated the same as a vector with angle 1/4 * pi.
%
% Each gradient vector's contribution is split between the two nearest bins,
% in proportion to the distance between the two nearest bin centers.
%
% A gradient's contribution to the histogram is equal to its magnitude;
% the magnitude is divided between the two nearest bin centers.
%
% Parameters:
% magnitudes - A column vector storing the magnitudes of the gradient
% vectors.
% angles - A column vector storing the angles in radians of the
% gradient vectors (ranging from -pi to pi)
% numBins - The number of bins to place the gradients into.
% Returns:
% A row vector of length 'numBins' containing the histogram.
% Compute the bin size in radians. 180 degress = pi.
binSize = pi / numBins;
% The angle values will range from 0 to pi.
minAngle = 0;
% Make the angles unsigned by adding pi (180 degrees) to all negative angles. angles(angles < 0) = angles(angles < 0) + pi;
% The gradient angle for each pixel will fall between two bin centers.
% For each pixel, we split the bin contributions between the bin to the left
% and the bin to the right bad on how far the angle is from the bin centers.
% For each pixel's gradient vector, determine the indeces of the bins to the
% left and right of the vector's angle.
%
% The histogram needs to wrap around at the edges--vectors on the far edges of % the histogram (i.e., clo to -pi or pi) will contribute partly to the bin
% at that edge, and partly to the bin on the other end of the histogram.
% For vectors with an orientation clo to 0 radians, leftBinIndex will be 0.
% Likewi, for vectors with an orientation clo to pi radians, rightBinIndex
% will be numBins + 1. We will fix the indeces after we calculate the bin
% contribution amounts.
leftBinIndex = round((angles - minAngle) / binSize);
rightBinIndex = leftBinIndex + 1;
% For each pixel, compute the center of the bin to the left.
leftBinCenter = ((leftBinIndex - 0.5) * binSize) - minAngle;
% For each pixel, compute the fraction of the magnitude
% to contribute to each bin.
rightPortions = angles - leftBinCenter;
leftPortions = binSize - rightPortions;
rightPortions = rightPortions / binSize;
leftPortions = leftPortions / binSize;
% Before using the bin indeces, we need to fix the '0' and '10' values.
% Recall that the histogram needs to wrap around at the edges--bin "0"
% contributions, for example, really belong in bin 9.
% Replace index 0 with 9 and index 10 with 1.
leftBinIndex(leftBinIndex == 0) = numBins;
rightBinIndex(rightBinIndex == (numBins + 1)) = 1;
% Create an empty row vector for the histogram.
H = zeros(1, numBins);
% For each
for i = 1:numBins
% Find the pixels with left bin == i
pixels = (leftBinIndex == i);
% For each of the lected pixels, add the gradient magnitude to bin 'i',
% weighted by the 'leftPortion' for that pixel.
H(1, i) = H(1, i) + sum(leftPortions(pixels)' * magnitudes(pixels));
% Find the pixels with right bin == i
pixels = (rightBinIndex == i);
% For each of the lected pixels, add the gradient magnitude to bin 'i',
% weighted by the 'rightPortion' for that pixel.
H(1, i) = H(1, i) + sum(rightPortions(pixels)' * magnitudes(pixels));
end
end