You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
440 lines
17 KiB
440 lines
17 KiB
"""
|
|
Programmer : EOF
|
|
Date : 2016.01.16
|
|
E-mail : jasonleaster@163.com
|
|
File : haarFeature.py
|
|
|
|
Description:
|
|
|
|
Types of Haar-like rectangle features
|
|
--- ---
|
|
| + |
|
|
|-------|
|
|
| - |
|
|
-------
|
|
I
|
|
--- ---
|
|
| | |
|
|
| - | + |
|
|
| | |
|
|
--- ---
|
|
II
|
|
|
|
-- -- --
|
|
| | | |
|
|
|- | +| -|
|
|
| | | |
|
|
-- -- --
|
|
III
|
|
|
|
--- ---
|
|
|___-___|
|
|
|___+___|
|
|
|___-___|
|
|
IV
|
|
|
|
--- ---
|
|
| - | + |
|
|
|___|___|
|
|
| + | - |
|
|
|___|___|
|
|
V
|
|
|
|
For each feature pattern, the start point(x, y) is at
|
|
the most left-up pixel in that window. The size of that
|
|
window is @width * @height
|
|
"""
|
|
import numpy
|
|
|
|
from config import HAAR_FEATURE_TYPE_I
|
|
from config import HAAR_FEATURE_TYPE_II
|
|
from config import HAAR_FEATURE_TYPE_III
|
|
from config import HAAR_FEATURE_TYPE_IV
|
|
from config import HAAR_FEATURE_TYPE_V
|
|
|
|
from image import Image
|
|
|
|
|
|
class Feature:
|
|
def __init__(self, img_Width, img_Height):
|
|
|
|
self.featureName = "Haar Feature"
|
|
|
|
self.img_Width = img_Width
|
|
self.img_Height = img_Height
|
|
|
|
self.tot_pixels = img_Width * img_Height
|
|
|
|
self.featureTypes = (HAAR_FEATURE_TYPE_I,
|
|
HAAR_FEATURE_TYPE_II,
|
|
HAAR_FEATURE_TYPE_III,
|
|
HAAR_FEATURE_TYPE_IV,
|
|
HAAR_FEATURE_TYPE_V)
|
|
|
|
self.features = self._evalFeatures_total()
|
|
|
|
self.featuresNum = len(self.features)
|
|
|
|
#self.featureMat = numpy.zeros((self.tot_pixels, self.featuresNum),
|
|
# dtype=numpy.float16)
|
|
|
|
# just for running faster and save RAM. allocate once and use many times.
|
|
self.vector = numpy.zeros(self.featuresNum, dtype=numpy.float32)
|
|
|
|
self.idxVector_tmp_0 = numpy.zeros(self.tot_pixels, dtype = numpy.int8)
|
|
self.idxVector_tmp_1 = numpy.zeros(self.tot_pixels, dtype = numpy.int8)
|
|
self.idxVector_tmp_2 = numpy.zeros(self.tot_pixels, dtype = numpy.int8)
|
|
self.idxVector_tmp_3 = numpy.zeros(self.tot_pixels, dtype = numpy.int8)
|
|
|
|
|
|
def vecRectSum(self, idxVector, x, y, width, height):
|
|
idxVector *= 0 # reset this vector
|
|
if x == 0 and y == 0:
|
|
idxVector[width * height + 2] = +1
|
|
|
|
elif x == 0:
|
|
idx1 = self.img_Height * ( width - 1) + height + y - 1
|
|
idx2 = self.img_Height * ( width - 1) + y - 1
|
|
idxVector[idx1] = +1
|
|
idxVector[idx2] = -1
|
|
|
|
elif y == 0:
|
|
idx1 = self.img_Height * (x + width - 1) + height - 1
|
|
idx2 = self.img_Height * (x - 1) + height - 1
|
|
idxVector[idx1] = +1
|
|
idxVector[idx2] = -1
|
|
else:
|
|
idx1 = self.img_Height * (x + width - 1) + height + y - 1
|
|
idx2 = self.img_Height * (x + width - 1) + y - 1
|
|
idx3 = self.img_Height * (x - 1) + height + y - 1
|
|
idx4 = self.img_Height * (x - 1) + y - 1
|
|
|
|
assert idx1 < self.tot_pixels and idx2 < self.tot_pixels
|
|
assert idx3 < self.tot_pixels and idx4 < self.tot_pixels
|
|
|
|
idxVector[idx1] = + 1
|
|
idxVector[idx2] = - 1
|
|
idxVector[idx3] = - 1
|
|
idxVector[idx4] = + 1
|
|
|
|
return idxVector
|
|
|
|
|
|
def VecFeatureTypeI(self, vecImg, x, y, width, height):
|
|
vec1 = self.vecRectSum(self.idxVector_tmp_0, x, y , width, height)
|
|
vec2 = self.vecRectSum(self.idxVector_tmp_1, x, y + height, width, height)
|
|
|
|
featureSize = width * height * 2
|
|
|
|
return (vec1.dot(vecImg) - vec2.dot(vecImg))/featureSize
|
|
|
|
|
|
def VecFeatureTypeII(self, vecImg, x, y, width, height):
|
|
vec1 = self.vecRectSum(self.idxVector_tmp_0, x + width, y, width, height)
|
|
vec2 = self.vecRectSum(self.idxVector_tmp_1, x , y, width, height)
|
|
|
|
featureSize = width * height * 2
|
|
|
|
return (vec1.dot(vecImg) - vec2.dot(vecImg))/featureSize
|
|
|
|
|
|
def VecFeatureTypeIII(self,vecImg, x, y, width, height):
|
|
vec1 = self.vecRectSum(self.idxVector_tmp_0, x + width, y, width, height)
|
|
vec2 = self.vecRectSum(self.idxVector_tmp_1, x , y, width, height)
|
|
vec3 = self.vecRectSum(self.idxVector_tmp_2, x + 2*width, y, width, height)
|
|
|
|
featureSize = width * height * 3
|
|
|
|
return (vec1.dot(vecImg) - vec2.dot(vecImg)
|
|
- vec3.dot(vecImg))/featureSize
|
|
|
|
|
|
def VecFeatureTypeIV(self,vecImg, x, y, width, height):
|
|
vec1 = self.vecRectSum(self.idxVector_tmp_0, x, y + height, width, height)
|
|
vec2 = self.vecRectSum(self.idxVector_tmp_1, x, y , width, height)
|
|
vec3 = self.vecRectSum(self.idxVector_tmp_2, x, y + 2*height, width, height)
|
|
|
|
featureSize = width * height * 3
|
|
|
|
return (vec1.dot(vecImg) - vec2.dot(vecImg)
|
|
- vec3.dot(vecImg))/featureSize
|
|
|
|
|
|
def VecFeatureTypeV(self, vecImg, x, y, width, height):
|
|
vec1 = self.vecRectSum(self.idxVector_tmp_0, x + width, y, width, height)
|
|
vec2 = self.vecRectSum(self.idxVector_tmp_1, x , y, width, height)
|
|
vec3 = self.vecRectSum(self.idxVector_tmp_2, x , y + height, width, height)
|
|
vec4 = self.vecRectSum(self.idxVector_tmp_3, x + width, y + height, width, height)
|
|
|
|
featureSize = width * height * 4
|
|
|
|
return (vec1.dot(vecImg) - vec2.dot(vecImg) +
|
|
vec3.dot(vecImg) - vec4.dot(vecImg))/featureSize
|
|
|
|
|
|
def _evalFeatures_total(self):
|
|
win_Height = self.img_Height
|
|
win_Width = self.img_Width
|
|
|
|
height_Limit = {HAAR_FEATURE_TYPE_I : win_Height//2 - 1,
|
|
HAAR_FEATURE_TYPE_II : win_Height - 1,
|
|
HAAR_FEATURE_TYPE_III : win_Height - 1,
|
|
HAAR_FEATURE_TYPE_IV : win_Height//3 - 1,
|
|
HAAR_FEATURE_TYPE_V : win_Height//2 - 1}
|
|
|
|
width_Limit = {HAAR_FEATURE_TYPE_I : win_Width - 1,
|
|
HAAR_FEATURE_TYPE_II : win_Width//2 - 1,
|
|
HAAR_FEATURE_TYPE_III : win_Width//3 - 1,
|
|
HAAR_FEATURE_TYPE_IV : win_Width - 1,
|
|
HAAR_FEATURE_TYPE_V : win_Width//2 - 1}
|
|
|
|
features = []
|
|
for types in self.featureTypes:
|
|
for w in range(1, width_Limit[types]):
|
|
for h in range(1, height_Limit[types]):
|
|
|
|
if w == 1 and h == 1:
|
|
continue
|
|
|
|
if types == HAAR_FEATURE_TYPE_I:
|
|
|
|
x_limit = win_Width - w
|
|
y_limit = win_Height - 2*h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_II:
|
|
x_limit = win_Width - 2*w
|
|
y_limit = win_Height - h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_III:
|
|
x_limit = win_Width - 3*w
|
|
y_limit = win_Height - h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
|
|
elif types == HAAR_FEATURE_TYPE_IV:
|
|
x_limit = win_Width - w
|
|
y_limit = win_Height - 3*h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_V:
|
|
x_limit = win_Width - 2*w
|
|
y_limit = win_Height - 2*h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
return features
|
|
|
|
|
|
def calFeatureForImg(self, img):
|
|
|
|
assert isinstance(img, Image)
|
|
assert img.img.shape[0] == self.img_Height
|
|
assert img.img.shape[1] == self.img_Width
|
|
|
|
for i in range(self.featuresNum):
|
|
type, x, y, w, h = self.features[i]
|
|
|
|
if type == HAAR_FEATURE_TYPE_I:
|
|
self.vector[i] = self.VecFeatureTypeI(img.vecImg, x, y, w, h)
|
|
elif type == HAAR_FEATURE_TYPE_II:
|
|
self.vector[i] = self.VecFeatureTypeII(img.vecImg, x, y, w, h)
|
|
elif type == HAAR_FEATURE_TYPE_III:
|
|
self.vector[i] = self.VecFeatureTypeIII(img.vecImg, x, y, w, h)
|
|
elif type == HAAR_FEATURE_TYPE_IV:
|
|
self.vector[i] = self.VecFeatureTypeIV(img.vecImg, x, y, w, h)
|
|
elif type == HAAR_FEATURE_TYPE_V:
|
|
self.vector[i] = self.VecFeatureTypeV(img.vecImg, x, y, w, h)
|
|
else:
|
|
raise Exception("unknown feature type")
|
|
|
|
return self.vector
|
|
|
|
|
|
def makeFeaturePic(self, feature):
|
|
|
|
from matplotlib import pyplot
|
|
from config import BLACK
|
|
from config import WHITE
|
|
import pylab
|
|
|
|
(types, x, y, width, height) = feature
|
|
|
|
assert x >= 0 and x < self.img_Width
|
|
assert y >= 0 and y < self.img_Height
|
|
assert width > 0 and height > 0
|
|
|
|
image = numpy.array([[125. for i in range(self.img_Width)]
|
|
for j in range(self.img_Height)])
|
|
|
|
if types == HAAR_FEATURE_TYPE_I:
|
|
for i in range(y, y + height * 2):
|
|
for j in range(x, x + width):
|
|
if i < y + height:
|
|
image[i][j] = BLACK
|
|
else:
|
|
image[i][j] = WHITE
|
|
|
|
elif types == HAAR_FEATURE_TYPE_II:
|
|
for i in range(y, y + height):
|
|
for j in range(x, x + width * 2):
|
|
if j < x + width:
|
|
image[i][j] = WHITE
|
|
else:
|
|
image[i][j] = BLACK
|
|
|
|
elif types == HAAR_FEATURE_TYPE_III:
|
|
for i in range(y, y + height):
|
|
for j in range(x, x + width * 3):
|
|
if j >= (x + width) and j < (x + width * 2):
|
|
image[i][j] = BLACK
|
|
else:
|
|
image[i][j] = WHITE
|
|
|
|
elif types == HAAR_FEATURE_TYPE_IV:
|
|
for i in range(y, y + height*3):
|
|
for j in range(x, x + width):
|
|
if i >= (y + height) and i < (y + height * 2):
|
|
image[i][j] = BLACK
|
|
else:
|
|
image[i][j] = WHITE
|
|
|
|
elif types == HAAR_FEATURE_TYPE_V:
|
|
for i in range(y, y + height * 2):
|
|
for j in range(x, x + width * 2):
|
|
if (j < x + width and i < y + height) or\
|
|
(j >= x + width and i >= y + height):
|
|
image[i][j] = BLACK
|
|
else:
|
|
image[i][j] = WHITE
|
|
|
|
|
|
pyplot.matshow(image, cmap = "gray")
|
|
pylab.show()
|
|
|
|
|
|
"""
|
|
old version. Don't use this.
|
|
def _evalFeatures(self):
|
|
win_Height = self.img_Height
|
|
win_Width = self.img_Width
|
|
|
|
height_Limit = {HAAR_FEATURE_TYPE_I : win_Height/2 - 1,
|
|
HAAR_FEATURE_TYPE_II : win_Height - 1,
|
|
HAAR_FEATURE_TYPE_III : win_Height - 1,
|
|
HAAR_FEATURE_TYPE_IV : win_Height/2 - 1}
|
|
|
|
width_Limit = {HAAR_FEATURE_TYPE_I : win_Width - 1,
|
|
HAAR_FEATURE_TYPE_II : win_Width/2 - 1,
|
|
HAAR_FEATURE_TYPE_III : win_Width/3 - 1,
|
|
HAAR_FEATURE_TYPE_IV : win_Width/2 - 1}
|
|
|
|
features = []
|
|
for types in self.featureTypes:
|
|
for w in range(1, width_Limit[types]):
|
|
for h in range(1, height_Limit[types]):
|
|
|
|
y_start = None
|
|
|
|
if types == HAAR_FEATURE_TYPE_I:
|
|
x_limit = win_Width - w
|
|
y_limit = win_Height - 2*h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit, 2):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_II:
|
|
x_limit = win_Width - 2*w
|
|
y_limit = win_Height - h
|
|
for x in range(1, x_limit):
|
|
if h % 2 == 1:
|
|
if x % 2 == 1:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
|
|
for y in range(y_start, y_limit, 2):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_III:
|
|
x_limit = win_Width - 3*w
|
|
y_limit = win_Height - h
|
|
for x in range(1, x_limit):
|
|
if w == 1:
|
|
if h % 2 == 1:
|
|
if (h + 1)/2 % 2 == 1:
|
|
if x % 2 == 1:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
else:
|
|
if x % 2 == 1:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
else:
|
|
if (h/2) % 2 == 1:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
elif w == 2:
|
|
if h % 2 == 1:
|
|
if x % 2 == 1:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
|
|
elif w == 3:
|
|
if h % 2 == 1:
|
|
if (h+1)/2 % 2 == 1:
|
|
if x % 2 == 1:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
else:
|
|
if x % 2 == 1:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
else:
|
|
if (h/2) % 2 == 1:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
#elif w == 4:
|
|
else:
|
|
if h % 2 == 1:
|
|
if x % 2 == 1:
|
|
y_start = 1
|
|
else:
|
|
y_start = 2
|
|
else:
|
|
y_start = 1
|
|
|
|
for y in range(y_start, y_limit, 2):
|
|
features.append( (types, x, y, w, h))
|
|
|
|
elif types == HAAR_FEATURE_TYPE_IV:
|
|
x_limit = win_Width - 2*w
|
|
y_limit = win_Height - 2*h
|
|
for x in range(1, x_limit):
|
|
for y in range(1, y_limit, 2):
|
|
features.append( (types, x, y, w, h))
|
|
return features
|
|
"""
|
|
|