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.

221 lines
8.0 KiB

"""
Programmer : EOF
File : detector.py
E-mail : jasonleaster@163.com
Date : 2016.01.18
"""
from config import TRAINING_IMG_WIDTH
from config import TRAINING_IMG_HEIGHT
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 AB_TH
from config import SEARCH_WIN_STEP
from image import Image
from haarFeature import Feature
from matplotlib import pyplot
from adaboost import getCachedAdaBoost
import pylab
import numpy
class Detector:
def __init__(self):
pass
def scanImgAtScale(self, model, image, scale):
assert isinstance(image, numpy.ndarray)
ImgHeight, ImgWidth = image.shape
SEARCH_WIN_WIDTH = int(TRAINING_IMG_WIDTH * scale)
SEARCH_WIN_HEIGHT = int(TRAINING_IMG_HEIGHT * scale)
width = ImgWidth - SEARCH_WIN_WIDTH - 10
height = ImgHeight - SEARCH_WIN_HEIGHT - 10
step = SEARCH_WIN_WIDTH // SEARCH_WIN_STEP
subWinNum = (width // step + 1) * (height // step + 1)
subImages = numpy.zeros(subWinNum, dtype=object)
subWins = numpy.zeros(subWinNum, dtype=object)
idx = 0
for x in range(0, width, step):
for y in range(0, height, step):
subWins[idx] = (x, y, SEARCH_WIN_WIDTH, SEARCH_WIN_HEIGHT)
subImages[idx] = Image(Mat=image[y:y + SEARCH_WIN_HEIGHT, x:x + SEARCH_WIN_WIDTH])
idx += 1
assert idx <= subWinNum
subImgNum = idx
selFeatures = numpy.zeros(model.N, dtype=object)
haar_scaled = Feature(SEARCH_WIN_WIDTH, SEARCH_WIN_HEIGHT)
haar_train = Feature(TRAINING_IMG_WIDTH, TRAINING_IMG_HEIGHT)
for n in range(model.N):
selFeatures[n] = haar_train.features[model.G[n].opt_dimension] + tuple([model.G[n].opt_dimension])
mat = numpy.zeros((haar_train.featuresNum, subImgNum), dtype=numpy.float16)
for feature in selFeatures:
(types, x, y, w, h, dim) = feature
x = int(x * scale)
y = int(y * scale)
w = int(w * scale)
h = int(h * scale)
for i in range(subImgNum):
if types == HAAR_FEATURE_TYPE_I:
mat[dim][i] = haar_scaled.VecFeatureTypeI(subImages[i].vecImg, x, y, w, h)
elif types == HAAR_FEATURE_TYPE_II:
mat[dim][i] = haar_scaled.VecFeatureTypeII(subImages[i].vecImg, x, y, w, h)
elif types == HAAR_FEATURE_TYPE_III:
mat[dim][i] = haar_scaled.VecFeatureTypeIII(subImages[i].vecImg, x, y, w, h)
elif types == HAAR_FEATURE_TYPE_IV:
mat[dim][i] = haar_scaled.VecFeatureTypeIV(subImages[i].vecImg, x, y, w, h)
output = model.grade(mat)
rectangle = []
for i in range(len(output)):
if output[i] > AB_TH:
candidate = numpy.array(subWins[i])
x, y, w, h = candidate
rectangle.append((x, y, w, h, output[i]))
return rectangle
def scanImgOverScale(self, image):
from config import DETECT_START
from config import DETECT_END
from config import DETECT_STEP
from config import ADABOOST_CACHE_FILE
from config import ADABOOST_LIMIT
model = getCachedAdaBoost(filename=ADABOOST_CACHE_FILE + str(0), limit=ADABOOST_LIMIT)
rectangles = []
for scale in numpy.arange(DETECT_START, DETECT_END, DETECT_STEP):
rectangles += self.scanImgAtScale(model, image, scale)
return self.optimalRectangle(rectangles)
def optimalRectangle(self, rectangles):
# number of rectangles
numRec = len(rectangles)
for i in range(numRec):
for j in range(i + 1, numRec):
if rectangles[i][4] < rectangles[j][4]:
rectangles[i], rectangles[j] = \
tuple(rectangles[j]), tuple(rectangles[i])
"""
(x1, y1, w1, h1) represent as the first rectangle.
(x2, y2, w2, h2) represent as the second rectangle.
|-------> x
| _______
|| 1 __|____
||____|__| |
| |____2__|
\/ y
"""
reduced = [i for i in range(numRec)]
for i in range(numRec):
x1, y1, w1, h1, score1 = rectangles[i]
area_1 = w1 * h1
for j in range(i + 1, numRec):
x2, y2, w2, h2, score2 = rectangles[j]
area_2 = h2 * w2
if (self.pointInRectangle((x2, y2), rectangles[i]) or
self.pointInRectangle((x2 + w2, y2), rectangles[i]) or
self.pointInRectangle((x2, y2 + h2), rectangles[i]) or
self.pointInRectangle((x2 + w2, y2 + h2), rectangles[i]) or
self.pointInRectangle((x2 + w2 / 2, y2), rectangles[i]) or
self.pointInRectangle((x2, y2 + h2 / 2), rectangles[i]) or
self.pointInRectangle((x2 + w2, y2 + h2 / 2), rectangles[i]) or
self.pointInRectangle((x2 + w2 / 2, y2 + h2), rectangles[i])) is True:
reduced[j] = reduced[i]
if (self.pointInRectangle((x1, y1), rectangles[j]) or
self.pointInRectangle((x1 + w1, y1), rectangles[j]) or
self.pointInRectangle((x1, y1 + h1), rectangles[j]) or
self.pointInRectangle((x1 + w1, y1 + h1), rectangles[j]) or
self.pointInRectangle((x1 + w1 / 2, y1), rectangles[j]) or
self.pointInRectangle((x1, y1 + h1 / 2), rectangles[j]) or
self.pointInRectangle((x1 + w1, y1 + h1 / 2), rectangles[j]) or
self.pointInRectangle((x1 + w1 / 2, y1 + h1), rectangles[j])) is True:
reduced[j] = reduced[i]
reducedRectangels = []
for i in numpy.unique(reduced):
reducedRectangels.append(rectangles[i])
return reducedRectangels
def pointInRectangle(self, point, rectangle):
m, n = point
x, y, w, h, _ = rectangle
if ((x < m and m < x + w) and (y < n and n < y + h)):
return True
else:
return False
def drawRectangle(self, image, x, y, width, height):
assert isinstance(image, numpy.ndarray)
if len(image.shape) != 2:
Row, Col, _ = image.shape
if x + width >= Col or y + height >= Row:
return
image[y:y + height, x - 1:x + 1, 0] = 0
image[y:y + height, x - 1:x + 1, 1] = 255
image[y:y + height, x - 1:x + 1, 2] = 0
image[y:y + height, (x - 1 + width):(x + 1 + width), 0] = 0
image[y:y + height, (x - 1 + width):(x + 1 + width), 1] = 255
image[y:y + height, (x - 1 + width):(x + 1 + width), 2] = 0
image[y - 1:y + 1, x:x + width, 0] = 0
image[y - 1:y + 1, x:x + width, 1] = 255
image[y - 1:y + 1, x:x + width, 2] = 0
image[(y - 1 + height):(y + height + 1), x:x + width, 0] = 0
image[(y - 1 + height):(y + height + 1), x:x + width, 1] = 255
image[(y - 1 + height):(y + height + 1), x:x + width, 2] = 0
else:
Row, Col = image.shape
if x + width >= Col or y + height >= Row:
return
image[y:y + height, x - 1:x + 1] = 255
image[y:y + height, x - 1 + width:x + 1 + width] = 255
image[y - 1:y + 1, x:x + width] = 255
image[y - 1 + height:y + 1 + height, x:x + width] = 255
pyplot.imshow(image)
pylab.show()
def showResult(self, image, rectangles):
for rectangle in rectangles:
x, y, width, height, score = rectangle
print(rectangle)
self.drawRectangle(image, x, y, width, height)