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

2 years ago
"""
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
"""