### Thread: Image processing using python, PIL,numpy and scipy

1. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Feb 2013
Posts
4
Rep Power
0

#### Image processing using python, PIL,numpy and scipy

Hi I am trying to do image processing with python.
what i actually want to do is i have image with human and i need to indetify humna faces or detect circle (basically human face).
what i have done so far us
• i have done edge detection for image using sobel edge detection.
• than i have converted image into binary image which saves binary image ad prints out array of the image which is 0 or 255 (Black and White)
• now what i m confused about after this what can i do to detect circle in image and print out how many human present in image.
• i am using still images so i am giving the input for the image

i am using Python, PIL, numpy and scipy. i do not want to use opencv. i want to detect human face and count how many people are in image and than print out the number of people in image.

i would be so greatful if someone can help me out and tell me what can i do for this problem?

THIS IS THE CODE FOR EDGE DETECTION
import numpy
import scipy
from scipy import ndimage

im = im.astype('int32')
dx = ndimage.sobel(im, 0) # horizontal derivative
dy = ndimage.sobel(im, 1) # vertical derivative
mag = numpy.hypot(dx, dy) # magnitude
mag *= 255.0 / numpy.max(mag) # normalize (Q&D)
scipy.misc.imsave('sobel.jpg', mag)

THIS IS THE CODE FOR BINARY CONVERSION OF IMAGE. THIS IS NOT MY CODE I FOUND THIS ONLINE WHEN I WAS SEARCHING HOW TO CONVERT IMAGE INTO BINARY IMAGE
## luminance conversion formula from

def luminosity(rgb, rcoeff=0.2126, gcoeff=0.7152, bcoeff=0.0722):
return rcoeff*rgb[0]+gcoeff*rgb[1]+bcoeff*rgb[2]

## take a PIL rgb image and produce a factory that yields
## ((x, y), (r, g, b)), where (x, y) are the coordinates
## of a pixel, (x, y), and its RGB values.
def gen_pix_factory(im):
num_cols, num_rows = im.size
r, c = 0, 0
while r != num_rows:
c = c % num_cols
yield ((c, r), im.getpixel((c, r)))
if c == num_cols - 1: r += 1
c += 1

## take a PIL RBG image and a luminosity conversion formula,
## and return a new gray level PIL image in which
## each pixel is obtained by applying the luminosity formula
## to the corresponding pixel in the RGB image.
def rgb_to_gray_level(rgb_img, conversion=luminosity):
gl_img = Image.new('L', rgb_img.size)
gen_pix = gen_pix_factory(im)
lum_pix = ((gp[0], conversion(gp[1])) for gp in gen_pix)
for lp in lum_pix:
gl_img.putpixel(lp[0], int(lp[1]))
return gl_img

## take a gray level image an a gray level threshold
## and replace a pixel's gray level with 0 (black) if
## its gray level value is <= than the threshold and
## with 255 (white) if it is > than the threshold.
def binarize(gl_img, thresh=70):
gen_pix = gen_pix_factory(gl_img)
for pix in gen_pix:
if pix[1] <= thresh:
gl_img.putpixel(pix[0], 0)
else:
gl_img.putpixel(pix[0], 255)

im = Image.open("Test.jpg")
gpix=gen_pix_factory(im)
[pix for pix in [gpix.next() for i in xrange(0, 286)] if pix[1] != (255, 255, 255)]

im2 = rgb_to_gray_level(im, conversion=luminosity) ## this will take a couple of seconds.
im2.save("picture.jpg")
binarize(im2)
im2.save("hello.jpg")
A =np.array(im2)
print A
2. #### Might work...

If you allowed additional input to your function, say it were the approximate radius of a head in the photo (in pixels) you could do a Hough transform on the edge-detected black and white image and then count the maxima in the resulting array.

More specifically,

Code:
```centers  is  a 2D  array  with each  index
corresponding  to  a  distance  along  the
axis, x or y.  Fill it with zeros.

for each pixel in the binary image:
if the pixel is an edge:
increment  all  centers  to  which
circles   of   approximately  that

count  the maxima  in  the centers  array,

Given this edge detected matrix, let us
figure out what happens to centers for the
pixel '-' .

Following matrix is the binary image,
which I might also have labeled BWIMAGE .

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    2
0 0 0 0 0 0 0 - 1 1 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0    4
0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    6
0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 * 0 0 0 0 0 0 0 0 0 1 0 0 0    .
0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0    .
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0    .
0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 * 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0   16

0   2   4   6  ...             16

We need a coordinate system---which I marked.

Our x and y axes are the same because I
chose a square matrix.  Suppose we use
this grid (follows) for the axes.
You will have to choose an appropriate
step size and bounds.  My grid is oversize
which allows for heads clipped by the
photo viewport.

_[0-9]+ denotes negative number.

XCENTER_GRID holds _5 _3 _1 1 3 5 7 9 11 13 15 17 19 21
YCENTER_GRID is the same.

Consider the dash at (7, 3).
Increment all the points in the centers
array satisfying
6 > sqrt((x-xc)**2 + (y-yc)**2) > 4

0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0 0 0 0
0 0 0 0 1 1 0 1 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0

Now add in 2 more edges to see how the
algorithm progresses.  These are the *
characters at (3,8) and (11,12)

centers becomes

0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 1 0 1 1 0 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 1 0 1 0 1 0 1 0 0 0 0 0
0 0 1 0 1 1 1 2 2 1 0 0 0 0
0 0 1 0 0 0 2 0 0 0 1 0 0 0
0 0 1 0 0 0 2 0 0 0 1 0 0 0
0 0 0 1 1 1 1 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0

Considering the entire binary image:
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 2 4 3 3 4 2 0 0 0 0
0 0 0 2 3 2 2 2 2 3 2 0 0 0
0 0 2 3 2 2 3 3 2 2 3 2 0 0
0 0 4 2 2 2 5 5 2 2 2 4 0 0
0 0 3 2 3 5 8 8 5 3 2 3 0 0
0 0 3 2 3 5 8 8 5 3 2 3 0 0
0 0 4 2 2 2 5 5 2 2 2 4 0 0
0 0 2 3 2 2 3 3 2 2 3 2 0 0
0 0 0 2 3 2 2 2 2 3 2 0 0 0
0 0 0 0 2 4 3 3 4 2 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0

Still  following?   centers  has a  single
maximum   and   if   you   backtrack   the
coordinates  through to  the  binary image
the maximum is in the right place.```
Last edited by b49P23TIvg; February 21st, 2013 at 02:13 PM. Reason: Sentence fragment removed.
3. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Feb 2013
Posts
4
Rep Power
0
hey i am sorry i do not understand what are you trying to say. i am not that expert in python. i have very basic knowledge about others as well. can you be more specific about it ? and one more thing you know the matrix you are showing how do i display that as because when i print array for image its not printing the matrix you have done here. Thanks
4. I wrote the examples using executable Iverson notation with a little bit of editing, only this time I didn't show the j code. There is a similarity between numpy array operations and j array operations. j displays arrays with maximum simplicity. Do you see extra commas or brackets??? The columns align although it's not obvious with binary data.

What about the algorithm don't you understand? I showed the Hough space center array after 3 various processing steps, I showed the inequality satisfied
6 > sqrt((x-xc)**2 + (y-yc)**2) > 4
corresponding to
I suppose I didn't say "5".

That
Code:
```for each pixel in the binary image:
if the pixel is an edge:
increment  all  centers  to  which
circles   of   approximately  that
represents 4 nested loops is, I agree, non-obvious.
5. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Feb 2013
Posts
4
Rep Power
0
I am sorry i have no idea what you talking about. and i did figure out when to display full matrix using numpy. even than i would not able able to create code using what are you explaining. as this requires me having very high level of numpy knowledge as well. can you give me example code?
instead of equation. entirely up to you. sorry if i am bothering you.

Originally Posted by b49P23TIvg
I wrote the examples using executable Iverson notation with a little bit of editing, only this time I didn't show the j code. There is a similarity between numpy array operations and j array operations. j displays arrays with maximum simplicity. Do you see extra commas or brackets??? The columns align although it's not obvious with binary data.

What about the algorithm don't you understand? I showed the Hough space center array after 3 various processing steps, I showed the inequality satisfied
6 > sqrt((x-xc)**2 + (y-yc)**2) > 4
corresponding to
I suppose I didn't say "5".

That
Code:
```for each pixel in the binary image:
if the pixel is an edge:
increment  all  centers  to  which
circles   of   approximately  that
represents 4 nested loops is, I agree, non-obvious.
6. I learned about the Hough transform here http://rosettacode.org/wiki/Hough_transform

If it's algebra that's confusing---what the heck are you doing trying to detect faces without knowing some math?
can you give me example code?
In which case start here (link).
7. No Profile Picture
Registered User
Devshed Newbie (0 - 499 posts)

Join Date
Feb 2013
Posts
4
Rep Power
0
its not the equation thats confusing whats hard for me it to convert equation into code. i do understand the maths by the way.
8. 6>sqrt((x-xc)**2+(y-yc)**2)>4

is a python expression that computes numerically to 0 or 1.

sqrt = lambda a:a**(0.5)
from math import sqrt
from numpy import sqrt

It's reasonable that you should learn about numpy before using it, likewise with python.
9. Data consists of circles with various radii,
noise, and a line. See attached image.

This Hough space is accumulates Cartesian coordinates that could be centers of circles within a range of radii.

1) Circle 1 makes a bright spot in Hough space.

2) Bright spot (yellow matrix element) of #2 comes from nearby objects that form 3 "lucky" segments. It's an artifact. The cutoff peak height determines whether you'd count it as a face.

3) 3 is a little too big but could be weighted more strongly since part of it is out of the viewport.

4) Ultra-enhanced by lucky coincidental features, and it's close to the target radius.

6) Too small, making a blob rather than a sharp peak.

7) (lower right) sketches the two circles that could have centers along the diagonal line
Code:
```#untested, assumes square matrices.
def hough(BWIMAGE, RMIN, RMAX, AXIS):
BW = numpy.array(BWIMAGE)# or asarray?
H = numpy.zeros((len(AXIS),len(AXIS)))
for (R, ROW,) in enumerate(BW):
Y = R/float(len(BW))
for (C, CELL,) in enumerate(Y):
if CELL:
X = CELL/float(len(ROW))
for (i,Cx,) in enumerate(AXIS):
DXDX = (X - Cx)**2
for (j, Cy) in enumerate(AXIS):
H[i,j] += RMIN < numpy.sqrt(DXDX+(Y-Cy)**2) < RMAX
return H```
inputs RMIN,RMAX bracket the radii range you'd seek. Faces are sort of oval, that's an advantage. Using equality test on a grid with floating point arithmetic is unsmart. BWIMAGE is the pixel array.
AXIS is a list of the trial centers, from 0 to 1. I used 60 values from -0.1 to 1.1 to allow for faces with centers off screen. Output is the Hough matrix.

>>> numpy.arange(9.0)/8 #AXIS
array([ 0. , 0.125, 0.25 , 0.375, 0.5 , 0.625, 0.75 , 0.875, 1. ])
Last edited by b49P23TIvg; February 22nd, 2013 at 01:05 AM. Reason: insert attachment