You are on page 1of 6

I = 'image_0058.

jpg';
bin = 8;
angle = 360;
L=3;
roi = [1;225;1;300];
p = anna_phog(I,bin,angle,L,roi)

function p = anna_phog(I,bin,angle,L,roi)
% anna_PHOG Computes Pyramid Histogram of Oriented Gradient over a ROI.
% [BH, BV] = anna_PHOG(I,BIN,ANGLE,L,ROI) computes phog descriptor over a ROI.
% Given and image I, phog computes the Pyramid Histogram of Oriented Gradients
% over L pyramid levels and over a Region Of Interest
%IN:
% I - Images of size MxN (Color or Gray)
% bin - Number of bins on the histogram
% angle - 180 or 360
% L - number of pyramid levels
% roi - Region Of Interest (ytop,ybottom,xleft,xright)
%
%OUT:
% p - pyramid histogram of oriented gradients
Img = imread(I);
if size(Img,3) == 3
G = rgb2gray(Img);
else
G = Img;
end
bh = [];
bv = [];

if sum(sum(G))>100
E = edge(G,'canny');
[GradientX,GradientY] = gradient(double(G));
GradientYY = gradient(GradientY);
Gr = sqrt((GradientX.*GradientX)+(GradientY.*GradientY));

index = GradientX == 0;
GradientX(index) = 1e-5;

YX = GradientY./GradientX;
if angle == 180, A = ((atan(YX)+(pi/2))*180)/pi; end
if angle == 360, A = ((atan2(GradientY,GradientX)+pi)*180)/pi; end

[bh bv] = anna_binMatrix(A,E,Gr,angle,bin);


else
bh = zeros(size(I,1),size(I,2));
bv = zeros(size(I,1),size(I,2));
end

bh_roi = bh(roi(1,1):roi(2,1),roi(3,1):roi(4,1));
bv_roi = bv(roi(1,1):roi(2,1),roi(3,1):roi(4,1));
p = anna_phogDescriptor(bh_roi,bv_roi,L,bin);
s = sprintf('%s.txt',I);
dlmwrite(s,p);
function [bm bv] = anna_BinMatrix(A,E,G,angle,bin)
% anna_BINMATRIX Computes a Matrix (bm) with the same size of the image where
% (i,j) position contains the histogram value for the pixel at position (i,j)
% and another matrix (bv) where the position (i,j) contains the gradient
% value for the pixel at position (i,j)
%
%IN:
% A - Matrix containing the angle values
% E - Edge Image
% G - Matrix containing the gradient values
% angle - 180 or 360%
% bin - Number of bins on the histogram
% angle - 180 or 360
%OUT:
% bm - matrix with the histogram values
% bv - matrix with the graident values (only for the pixels belonging to
% and edge)

[contorns,n] = bwlabel(E);
X = size(E,2);
Y = size(E,1);
bm = zeros(Y,X);
bv = zeros(Y,X);

nAngle = angle/bin;

for i=1:n
[posY,posX] = find(contorns==i);
for j=1:size(posY,1)
pos_x = posX(j,1);
pos_y = posY(j,1);

b = ceil(A(pos_y,pos_x)/nAngle);
if b==0, bin= 1; end
if G(pos_y,pos_x)>0
bm(pos_y,pos_x) = b;
bv(pos_y,pos_x) = G(pos_y,pos_x);
end
end
end
function p = anna_PhogDescriptor(bh,bv,L,bin)
% anna_PHOGDESCRIPTOR Computes Pyramid Histogram of Oriented Gradient over a ROI.
%
%IN:
% bh - matrix of bin histogram values
% bv - matrix of gradient values
% L - number of pyramid levels
% bin - number of bins
%
%OUT:
% p - pyramid histogram of oriented gradients (phog descriptor)

p = [];
%level 0
for b=1:bin
ind = bh==b;
p = [p;sum(bv(ind))];
end

cella = 1;
for l=1:L
x = fix(size(bh,2)/(2^l));
y = fix(size(bh,1)/(2^l));
xx=0;
yy=0;
while xx+x<=size(bh,2)
while yy +y <=size(bh,1)
bh_cella = [];
bv_cella = [];

bh_cella = bh(yy+1:yy+y,xx+1:xx+x);
bv_cella = bv(yy+1:yy+y,xx+1:xx+x);

for b=1:bin
ind = bh_cella==b;
p = [p;sum(bv_cella(ind))];
end
yy = yy+y;
end
cella = cella+1;
yy = 0;
xx = xx+x;
end
end
if sum(p)~=0
p = p/sum(p);
end
import cv2

import math

import numpy as np

import argparse

from numba import jit

def printMatDetails(m, desc="matrix"):

print(f'{desc}: {m.dtype} {m.shape} [{m.min()}, {m.max()}], u: {m.mean()}, o: {m.std()}')

@jit

def getHistogram(edges, ors, mag, startX, startY, width, height, nbins):

hist = np.zeros(nbins)

for x in range(startX, startX + height):

for y in range(startY, startY + width):

if edges[x, y] > 0:

bin = math.floor(ors[x, y])

hist[bin] = hist[bin] + mag[x, y]

return hist

def compute_phog(img, nbins):

# Determine desc size

desc_size = nbins + 4 * nbins + 16 * nbins

# Convert the image to grayscale

if img.ndim == 3:

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# printMatDetails(img, 'Image BW')

# Reduce noise, Apply Canny Edge Detector

mean = np.mean(img)

edges = cv2.blur(img, (3,3))

# printMatDetails(edges, 'Image Blur')

edges = cv2.Canny(edges, 0.66 * mean, 1.33 * mean)

# printMatDetails(edges, 'edges')

# Computing the gradients.

grad_x = cv2.Sobel(img, cv2.CV_32F, 1, 0, ksize=3)


grad_y = cv2.Sobel(img, cv2.CV_32F, 0, 1, ksize=3)

# Total Gradient (approximate)

grad_m = np.abs(grad_x) + np.abs(grad_y)

# printMatDetails(grad_x, 'grad_x')

# printMatDetails(grad_y, 'grad_y')

# printMatDetails(grad_m, 'grad_m')

# Computing orientations

grad_o = cv2.phase(grad_x, grad_y, angleInDegrees=True)

# printMatDetails(grad_o, 'grad_o')

# Quantizing orientations into bins.

w = 360.0 / nbins

grad_o = grad_o / w

# printMatDetails(grad_o, 'grad_o')

# Creating the descriptor.

desc = np.zeros(desc_size, dtype=np.float32)

width = img.shape[1]

height = img.shape[0]

# Level 0

desc[0:nbins] = getHistogram(edges, grad_o, grad_m, 0, 0, width, height, nbins)

# cv2.imshow('image', img)

# Level 1

desc[nbins:nbins*2] = getHistogram(edges, grad_o, grad_m, 0, 0, width // 2, height // 2, nbins)

desc[nbins*2:nbins*3] = getHistogram(edges, grad_o, grad_m, 0, width // 2, width // 2, height // 2, nbins)

desc[nbins*3:nbins*4] = getHistogram(edges, grad_o, grad_m, height // 2, 0, width // 2, height // 2, nbins)

desc[nbins*4:nbins*5] = getHistogram(edges, grad_o, grad_m, height // 2, width // 2, width // 2, height //


2, nbins)

# Level 2

wstep = width // 4

hstep = height // 4

binPos = 5 # Next free section in the histogram

for i in range(4):

for j in range(4):
desc[nbins*binPos:nbins*(binPos+1)] = getHistogram(edges, grad_o, grad_m, i * hstep, j * wstep,
wstep, hstep, nbins)

binPos += 1

# Normalizing the histogram

desc = desc / desc.sum()

return desc

def main():

parser = argparse.ArgumentParser()

parser.add_argument('img_path', help='Path to img')

parser.add_argument('--nbins', type=int, default=60, help='Number of orientation bins')

parser.add_argument('--pyramid_height', type=int, default=2, help='Number of levels in the pyramid')

args = parser.parse_args()

# Read image

img = cv2.imread(args.img_path)

printMatDetails(img, 'Image')

desc = compute_phog(img, nbins=args.nbins)

printMatDetails(desc, 'Gdsc')

filename = 'data/desc_py.txt'

np.savetxt(filename, desc)

print(f'Successfully saved {filename}')

if __name__ == '__main__':

main()

You might also like