Browse Source

All sorts of test scripts and the first functional mirror version

testqueue
Ruben van de Ven 2 years ago
commit
cf94593382
  1. 1790
      dnn/deploy.prototxt
  2. 1790
      dnn/deploy_lowres.prototxt
  3. 2
      dnn/face_detector/.gitignore
  4. 1790
      dnn/face_detector/deploy.prototxt
  5. 1790
      dnn/face_detector/deploy_lowres.prototxt
  6. 74
      dnn/face_detector/download_weights.py
  7. 79
      dnn/face_detector/how_to_train_face_detector.txt
  8. 2368
      dnn/face_detector/opencv_face_detector.pbtxt
  9. 28
      dnn/face_detector/solver.prototxt
  10. 1831
      dnn/face_detector/test.prototxt
  11. 1898
      dnn/face_detector/train.prototxt
  12. 13
      dnn/face_detector/weights.meta4
  13. 79
      dnn_test.py
  14. 0
      face_recognition/__init__.py
  15. BIN
      face_recognition/__pycache__/__init__.cpython-38.pyc
  16. BIN
      face_recognition/__pycache__/comparison.cpython-38.pyc
  17. BIN
      face_recognition/__pycache__/hog.cpython-38.pyc
  18. 447
      face_recognition/comparison.py
  19. 256
      face_recognition/hog.py
  20. 20719
      haarcascade_frontalface_alt2.xml
  21. 55
      hog_test.py
  22. 99
      live_dnn.py
  23. 71
      live_hog.py
  24. 10
      mirror.py
  25. 20
      recognition_test.py
  26. 4
      requirements.txt
  27. 79
      test_rec.py
  28. 89
      test_rust.py
  29. 97
      video_multiprocess.py
  30. 36
      video_threading.py

1790
dnn/deploy.prototxt

File diff suppressed because it is too large Load Diff

1790
dnn/deploy_lowres.prototxt

File diff suppressed because it is too large Load Diff

2
dnn/face_detector/.gitignore vendored

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
*.caffemodel
*.pb

1790
dnn/face_detector/deploy.prototxt

File diff suppressed because it is too large Load Diff

1790
dnn/face_detector/deploy_lowres.prototxt

File diff suppressed because it is too large Load Diff

74
dnn/face_detector/download_weights.py

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
#!/usr/bin/env python
from __future__ import print_function
import hashlib
import time
import sys
import xml.etree.ElementTree as ET
if sys.version_info[0] < 3:
from urllib2 import urlopen
else:
from urllib.request import urlopen
class HashMismatchException(Exception):
def __init__(self, expected, actual):
Exception.__init__(self)
self.expected = expected
self.actual = actual
def __str__(self):
return 'Hash mismatch: {} vs {}'.format(self.expected, self.actual)
class MetalinkDownloader(object):
BUFSIZE = 10*1024*1024
NS = {'ml': 'urn:ietf:params:xml:ns:metalink'}
tick = 0
def download(self, metalink_file):
status = True
for file_elem in ET.parse(metalink_file).getroot().findall('ml:file', self.NS):
url = file_elem.find('ml:url', self.NS).text
fname = file_elem.attrib['name']
hash_sum = file_elem.find('ml:hash', self.NS).text
print('*** {}'.format(fname))
try:
self.verify(hash_sum, fname)
except Exception as ex:
print(' {}'.format(ex))
try:
print(' {}'.format(url))
with open(fname, 'wb') as file_stream:
self.buffered_read(urlopen(url), file_stream.write)
self.verify(hash_sum, fname)
except Exception as ex:
print(' {}'.format(ex))
print(' FAILURE')
status = False
continue
print(' SUCCESS')
return status
def print_progress(self, msg, timeout = 0):
if time.time() - self.tick > timeout:
print(msg, end='')
sys.stdout.flush()
self.tick = time.time()
def buffered_read(self, in_stream, processing):
self.print_progress(' >')
while True:
buf = in_stream.read(self.BUFSIZE)
if not buf:
break
processing(buf)
self.print_progress('>', 5)
print(' done')
def verify(self, hash_sum, fname):
sha = hashlib.sha1()
with open(fname, 'rb') as file_stream:
self.buffered_read(file_stream, sha.update)
if hash_sum != sha.hexdigest():
raise HashMismatchException(hash_sum, sha.hexdigest())
if __name__ == '__main__':
sys.exit(0 if MetalinkDownloader().download('weights.meta4') else 1)

79
dnn/face_detector/how_to_train_face_detector.txt

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
This is a brief description of training process which has been used to get res10_300x300_ssd_iter_140000.caffemodel.
The model was created with SSD framework using ResNet-10 like architecture as a backbone. Channels count in ResNet-10 convolution layers was significantly dropped (2x- or 4x- fewer channels).
The model was trained in Caffe framework on some huge and available online dataset.
1. Prepare training tools
You need to use "ssd" branch from this repository https://github.com/weiliu89/caffe/tree/ssd . Checkout this branch and built it (see instructions in repo's README)
2. Prepare training data.
The data preparation pipeline can be represented as:
(a)Download original face detection dataset -> (b)Convert annotation to the PASCAL VOC format -> (c)Create LMDB database with images + annotations for training
a) Find some datasets with face bounding boxes annotation. For some reasons I can't provide links here, but you easily find them on your own. Also study the data. It may contain small or low quality faces which can spoil training process. Often there are special flags about object quality in annotation. Remove such faces from annotation (smaller when 16 along at least one side, or blurred, of highly-occluded, or something else).
b) The downloaded dataset will have some format of annotation. It may be one single file for all images, or separate file for each image or something else. But to train SSD in Caffe you need to convert annotation to PASCAL VOC format.
PASCAL VOC annotation consist of .xml file for each image. In this xml file all face bounding boxes should be listed as:
<annotation>
<size>
<width>300</width>
<height>300</height>
</size>
<object>
<name>face</name>
<difficult>0</difficult>
<bndbox>
<xmin>100</xmin>
<ymin>100</ymin>
<xmax>200</xmax>
<ymax>200</ymax>
</bndbox>
</object>
<object>
<name>face</name>
<difficult>0</difficult>
<bndbox>
<xmin>0</xmin>
<ymin>0</ymin>
<xmax>100</xmax>
<ymax>100</ymax>
</bndbox>
</object>
</annotation>
So, convert your dataset's annotation to the format above.
Also, you should create labelmap.prototxt file with the following content:
item {
name: "none_of_the_above"
label: 0
display_name: "background"
}
item {
name: "face"
label: 1
display_name: "face"
}
You need this file to establish correspondence between name of class and digital label of class.
For next step we also need file there all our image-annotation file names pairs are listed. This file should contain similar lines:
images_val/0.jpg annotations_val/0.jpg.xml
c) To create LMDB you need to use create_data.sh tool from caffe/data/VOC0712 Caffe's source code directory.
This script calls create_annoset.py inside, so check out what you need to pass as script's arguments
You need to prepare 2 LMDB databases: one for training images, one for validation images.
3. Train your detector
For training you need to have 3 files: train.prototxt, test.prototxt and solver.prototxt. You can find these files in the same directory as for this readme.
Also you need to edit train.prototxt and test.prototxt to replace paths for your LMDB databases to actual databases you've created in step 2.
Now all is done for launch training process.
Execute next lines in Terminal:
mkdir -p snapshot
mkdir -p log
/path_for_caffe_build_dir/tools/caffe train -solver="solver.prototxt" -gpu 0 2>&1 | tee -a log/log.log
And wait. It will take about 8 hours to finish the process.
After it you can use your .caffemodel from snapshot/ subdirectory in resnet_face_ssd_python.py sample.

2368
dnn/face_detector/opencv_face_detector.pbtxt

File diff suppressed because it is too large Load Diff

28
dnn/face_detector/solver.prototxt

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
train_net: "train.prototxt"
test_net: "test.prototxt"
test_iter: 2312
test_interval: 5000
test_initialization: true
base_lr: 0.01
display: 10
lr_policy: "multistep"
max_iter: 140000
stepvalue: 80000
stepvalue: 120000
gamma: 0.1
momentum: 0.9
weight_decay: 0.0005
average_loss: 500
iter_size: 1
type: "SGD"
solver_mode: GPU
random_seed: 0
debug_info: false
snapshot: 1000
snapshot_prefix: "snapshot/res10_300x300_ssd"
eval_type: "detection"
ap_version: "11point"

1831
dnn/face_detector/test.prototxt

File diff suppressed because it is too large Load Diff

1898
dnn/face_detector/train.prototxt

File diff suppressed because it is too large Load Diff

13
dnn/face_detector/weights.meta4

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<metalink xmlns="urn:ietf:params:xml:ns:metalink">
<file name="res10_300x300_ssd_iter_140000_fp16.caffemodel">
<identity>OpenCV face detector FP16 weights</identity>
<hash type="sha-1">31fc22bfdd907567a04bb45b7cfad29966caddc1</hash>
<url>https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180205_fp16/res10_300x300_ssd_iter_140000_fp16.caffemodel</url>
</file>
<file name="opencv_face_detector_uint8.pb">
<identity>OpenCV face detector UINT8 weights</identity>
<hash type="sha-1">4f2fdf6f231d759d7bbdb94353c5a68690f3d2ae</hash>
<url>https://raw.githubusercontent.com/opencv/opencv_3rdparty/dnn_samples_face_detector_20180220_uint8/opencv_face_detector_uint8.pb</url>
</file>
</metalink>

79
dnn_test.py

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
# import face_recognition
import cv2
from skimage.feature import hog
from skimage import data, exposure
import matplotlib.pyplot as plt
import numpy as np
import dlib
import time
imagefile = "Marjo.jpg"
prototxt = "dnn/face_detector/opencv_face_detector.pbtxt"
prototxt = "dnn/face_detector/deploy.prototxt"
model = "dnn/face_detector/res10_300x300_ssd_iter_140000_fp16.caffemodel"
confidence_threshold = .0
image = cv2.imread(imagefile)
# rows = open(args["labels"]).read().strip().split("\n")
# classes = [r[r.find(" ") + 1:].split(",")[0] for r in rows]
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
print("[INFO] loding model...")
net = cv2.dnn.readNetFromCaffe(prototxt, model)
print("Loaded")
net.setInput(blob)
start = time.time()
detections = net.forward()
end = time.time()
print("[INFO] classification took {:.5} seconds".format(end-start))
idxs = np.argsort(detections[0])[::-1][:5]
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
# compute the (x, y)-coordinates of the bounding box for the
# object
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
# we always draw
# First we crop the sub-rect from the image
sub_img = image[startY:endY, startX:endX]
rect_img = sub_img.copy()
width = 2
cv2.rectangle(rect_img, (0, 0), (sub_img.shape[1]-int(width/2), sub_img.shape[0]-int(width/2)),
(0, 0, 255), width)
# white_rect = np.ones(sub_img.shape, dtype=np.uint8) * 255
# At least 10% opacity
alpha = max(.1, confidence)
res = cv2.addWeighted(sub_img, 1-alpha, rect_img, alpha, 1.0)
# Putting the image back to its position
image[startY:endY, startX:endX] = res
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > confidence_threshold:
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
# cv2.rectangle(image, (startX, startY), (endX, endY),
# (0, 0, 255), 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
# show the output image
cv2.imshow("Output", image)
cv2.waitKey(0)

0
face_recognition/__init__.py

BIN
face_recognition/__pycache__/__init__.cpython-38.pyc

Binary file not shown.

BIN
face_recognition/__pycache__/comparison.cpython-38.pyc

Binary file not shown.

BIN
face_recognition/__pycache__/hog.cpython-38.pyc

Binary file not shown.

447
face_recognition/comparison.py

@ -0,0 +1,447 @@ @@ -0,0 +1,447 @@
from multiprocessing import Process, Queue
from queue import Empty, Full
import cv2
import logging
import argparse
import numpy as np
import time
draw_colors = {
'dnn': (255,0,0),
'haar': (0,255,0),
'hog': (0,0,255),
}
ft = cv2.freetype.createFreeType2()
ft.loadFontData(fontFileName='Ubuntu-R.ttf',
id=0)
class Result():
def __init__(self, algorithm, image, confidence_threshold = 0.5):
self.algorithm = algorithm
self.visualisation = image
self.detections = []
self.confidence_threshold = confidence_threshold
def add_detection(self, startX, startY, endX, endY, confidence):
self.detections.append({
'startX': startX,
'startY': startY,
'endX': endX,
'endY': endY,
'confidence': confidence
})
return self
def draw_detections(self):
color = draw_colors[self.algorithm]
for detection in self.detections:
self.draw_detection(detection, color)
def draw_detection(self, detection, color=(0,0,255)):
# First we crop the sub-rect from the image
sub_img = self.visualisation[detection['startY']:detection['endY'], detection['startX']:detection['endX']]
rect_img = sub_img.copy()
width = 2
cv2.rectangle(rect_img, (0, 0),
(sub_img.shape[1]-int(width/2), sub_img.shape[0]-int(width/2)),
color, width)
# white_rect = np.ones(sub_img.shape, dtype=np.uint8) * 255
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if detection['confidence'] > self.confidence_threshold:
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(detection['confidence'] * 100)
y = detection['startY'] - 10 if detection['startY'] - 10 > 10 else detection['startY'] + 10
# cv2.rectangle(image, (startX, startY), (endX, endY),
# color, 2)
cv2.putText(self.visualisation, text, (detection['startX'], y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2, lineType = cv2.LINE_AA)
alpha = 1
else:
# At least 10% opacity
alpha = max(.3, detection['confidence'])
res = cv2.addWeighted(sub_img, 1-alpha, rect_img, alpha, 1.0)
# Putting the image back to its position
self.visualisation[detection['startY']:detection['endY'], detection['startX']:detection['endX']] = res
def resize(self, width, height):
# TODO resize to new target incl all detections
img = self.visualisation
factor_x = width / self.visualisation.shape[1]
factor_y = height / self.visualisation.shape[0]
inter = cv2.INTER_NEAREST if self.algorithm in ['dnn', 'haar'] else cv2.INTER_CUBIC
img = cv2.resize(img, (width, height), interpolation=inter)
result = Result(self.algorithm, img, self.confidence_threshold)
for d in self.detections:
result.add_detection(
int(d['startX'] * factor_x),
int(d['startY'] * factor_y),
int(d['endX'] * factor_x),
int(d['endY'] * factor_y),
d['confidence']
)
return result
def record(device_id, q1,q2, q3, q4):
capture = cv2.VideoCapture(device_id)
while True:
ret, image = capture.read()
logging.debug('r')
try:
q1.put_nowait(image)
except Full as e:
# ignore if processing doesn't keep up
pass
try:
q2.put_nowait(image)
except Full as e:
# ignore if processing doesn't keep up
pass
try:
q3.put_nowait(image)
except Full as e:
# ignore if processing doesn't keep up
pass
try:
q4.put_nowait(image)
except Full as e:
# ignore if processing doesn't keep up
pass
def draw_detection(image, startX, startY, endX, endY, confidence, color=(0,0,255), confidence_threshold = .5):
# First we crop the sub-rect from the image
sub_img = image[startY:endY, startX:endX]
rect_img = sub_img.copy()
width = 2
cv2.rectangle(rect_img, (0, 0),
(sub_img.shape[1]-int(width/2), sub_img.shape[0]-int(width/2)),
color, width)
# white_rect = np.ones(sub_img.shape, dtype=np.uint8) * 255
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > confidence_threshold:
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
# cv2.rectangle(image, (startX, startY), (endX, endY),
# color, 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, color, 2)
alpha = 1
else:
# At least 10% opacity
alpha = max(.3, confidence)
res = cv2.addWeighted(sub_img, 1-alpha, rect_img, alpha, 1.0)
# Putting the image back to its position
image[startY:endY, startX:endX] = res
def process1_hog(in_q, out_q):
from skimage.feature import hog as hog_orig
from .hog import hog # use modified version for viz
from skimage import data, exposure
import matplotlib.pyplot as plt
import dlib
face_detector = dlib.get_frontal_face_detector()
visualisation_factor = 1
detection_factor = .4
process_this_frame = True
while True:
if process_this_frame:
# Grab a single frame of video
frame = in_q.get()
frame = cv2.cvtColor(src=frame, code=cv2.COLOR_BGR2GRAY)
viz_frame = cv2.resize(frame, (0, 0), fx=visualisation_factor, fy=visualisation_factor)
det_frame = cv2.resize(frame, (0, 0), fx=detection_factor, fy=detection_factor)
start = time.time()
fd, hog_image = hog(det_frame, orientations=6, pixels_per_cell=(8, 8),
cells_per_block=(1, 1), visualize=True, multichannel=False, visualize_factor=visualisation_factor/detection_factor)
logging.debug(f"Duration of hog viz: {time.time() - start}")
hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10))
# hog_image_rescaled = viz_frame
# Resize frame of video to 1/4 size for faster face recognition processing
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
# rgb_small_frame = det_frame[:, :, ::-1]
# dets, scores, idxs = face_detector.run(rgb_small_frame, 1, -2)
dets, scores, idxs = face_detector.run(det_frame, 1, -2)
# print(dets, scores, idxs)
hog_image_rescaled = (hog_image_rescaled.astype('float32') * 255).astype('uint8')
hog_image_rescaled = cv2.cvtColor(hog_image_rescaled, cv2.COLOR_GRAY2BGR)
result = Result('hog', hog_image_rescaled, 0)
# Display the results
for i, rectangle in enumerate(dets):
probability = scores[i]
# print(rectangle)
# Scale back up face locations since the frame we detected in was scaled to 1/4 size
top = int(rectangle.top() * (visualisation_factor / detection_factor))
right = int(rectangle.right() * (visualisation_factor / detection_factor))
bottom = int(rectangle.bottom() * (visualisation_factor / detection_factor))
left = int(rectangle.left() * (visualisation_factor / detection_factor))
result.add_detection(left, top, right, bottom,probability)
# draw_detection(hog_image_rescaled, left, top, right, bottom, probability, draw_colors['hog'], 0)
# brightness = int(min(255, (probability + 1)*255))
# # Draw a box around the face
# cv2.rectangle(hog_image_rescaled, (left, top), (right, bottom), (0,0,brightness), 2)
# # Draw a label with a name below the face
# cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
# Display the resulting image
out_q.put(result)
# print(cgray.shape)
process_this_frame = not process_this_frame
def process2_dnn(in_q, out_q):
logger = logging.getLogger('dnn')
prototxt = "dnn/face_detector/opencv_face_detector.pbtxt"
prototxt = "dnn/face_detector/deploy.prototxt"
model = "dnn/face_detector/res10_300x300_ssd_iter_140000_fp16.caffemodel"
confidence_threshold = 0.5
logger.info("[INFO] loding model...")
net = cv2.dnn.readNetFromCaffe(prototxt, model)
logger.info("Loaded")
while True:
image = in_q.get()
(h, w) = image.shape[:2]
image_small = cv2.resize(image, (300, 300))
(hs, ws) = image_small.shape[:2]
blob = cv2.dnn.blobFromImage(image_small, 1.0,
(300, 300), (104.0, 177.0, 123.0))
image = cv2.cvtColor(cv2.cvtColor(image_small, cv2.COLOR_BGR2GRAY), cv2.COLOR_GRAY2BGR)
net.setInput(blob)
detections = net.forward()
# idxs = np.argsort(detections[0])[::-1][:5]
result = Result('dnn', image)
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
# compute the (x, y)-coordinates of the bounding box for the
# object
# box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
box = detections[0, 0, i, 3:7] * np.array([ws, hs, ws, hs])
(startX, startY, endX, endY) = box.astype("int")
result.add_detection(startX, startY, endX, endY, confidence)
# draw_detection(image, startX, startY, endX, endY, confidence, draw_colors['dnn'])
out_q.put(result)
def process3_haar(in_q, out_q):
from cffi import FFI
from PIL import Image
import cv2
logger = logging.getLogger('haar')
ffi = FFI()
ffi.cdef("""
int test(int);
typedef void* haarclassifier;
haarclassifier classifier_new();
void scan_image(haarclassifier, size_t width,size_t height, char *input, char *buffer, size_t length, bool debug);
""")
C = ffi.dlopen("/home/ruben/Documents/Projecten/2020/rust/testproject/target/debug/libvisual_haarcascades_lib.so")
# print(C.test(9))
# i = Image.open("Marjo.jpg")
# width = i.size[0]
# height = i.size[0]
# use the rust lib to draw the visualisation
haar = C.classifier_new()
logger.info("Initialised haar classifier")
# opencv for the actual detections
faceCascade = cv2.CascadeClassifier('./haarcascade_frontalface_alt2.xml')
while True:
frame = in_q.get()
(height_orig, width_orig) = frame.shape[:2]
scale_factor = 3
width = int(width_orig/scale_factor)
height = int(height_orig/scale_factor)
frame = cv2.resize(frame, (width, height))
# Run the B&W version through opencv haar to detect faces
# for some reason the variable 'frame' is modified after
# running the visualisation, so we do this before
f = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(f)
pixel_format = "RGB" #The raytracer only supports one format
bytes_per_pixel = 3
buffer_len = width * height * bytes_per_pixel
buffer = ffi.new("char[]", buffer_len)
buffer2 = ffi.from_buffer("char[]", frame.tobytes())
# i = Image.open("/home/ruben/Documents/Projecten/(2020/rust/lena_orig.png")
# data = i.tobytes("raw", "RGB")
logger.info("Start haar scan")
start = time.time()
C.scan_image(haar, width, height, buffer2, buffer, buffer_len, False)
logger.info(f"Visualised scan into buffer: {buffer}")
print(f"duration: {time.time() - start}s")
img = Image.frombuffer(pixel_format, (width, height), ffi.buffer(buffer),
"raw", pixel_format, 0, 1)
img= np.array(img)
# a= np.frombuffer(ffi.buffer(buffer))
# a.reshape((height, width, bytes_per_pixel))
# flip RGB back to BGR
# img = img[:, :, ::-1]
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (width_orig, height_orig))
result = Result('haar', img)
for face in faces:
x1, y1, w, h = face
x2 = x1 + w
y2 = y1 + h
# print(img.shape)
# TODO: is scale factor ok here?
# draw_detection(img, x1 * scale_factor, y1 * scale_factor, x2 * scale_factor, y2 * scale_factor, 1, draw_colors['haar'],)
result.add_detection(x1 * scale_factor, y1 * scale_factor, x2 * scale_factor, y2 * scale_factor, 1)
# print(img)
out_q.put(result)
def display(image_res, q1, q2, q3, q4):
prev_image1 = np.zeros((image_res[1],image_res[0],3), np.uint8)
prev_image2 = np.zeros((image_res[1],image_res[0],3), np.uint8)
prev_image3 = np.zeros((image_res[1],image_res[0],3), np.uint8)
prev_image4 = np.zeros((image_res[1],image_res[0],3), np.uint8)
while True:
logging.debug('r')
try:
image1 = q1.get_nowait()
image1 = cv2.resize(image1, (image_res[0], image_res[1]))
prev_image1 = image1
except Empty as e:
image1 = prev_image1
try:
result2 = q2.get_nowait()
result2 = result2.resize(image_res[0], image_res[1])
result2.draw_detections()
image2 = result2.visualisation
# image2 = cv2.resize(image2, (image_res[0], image_res[1]))
prev_image2 = image2
except Empty as e:
image2 = prev_image2
try:
result3 = q3.get_nowait()
result3 = result3.resize(image_res[0], image_res[1])
result3.draw_detections()
image3 = result3.visualisation
# image3 = cv2.resize(image3, (image_res[0], image_res[1]))
prev_image3 = image3
except Empty as e:
image3 = prev_image3
try:
result4 = q4.get_nowait()
result4 = result4.resize(image_res[0], image_res[1])
result4.draw_detections()
image4 = result4.visualisation
# image4 = cv2.resize(image4, (image_res[0], image_res[1]))
prev_image4 = image4
except Empty as e:
image4 = prev_image4
img_concate_Verti1 = np.concatenate((image1,image2),axis=0)
img_concate_Verti2 = np.concatenate((image3,image4),axis=0)
grid_img = np.concatenate((img_concate_Verti1,img_concate_Verti2),axis=1)
cv2.imshow("Output", grid_img)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
def main(camera_id):
image_size = (int(1920/2), int(1080/2))
# TODO should we use queues here at all?
# https://docs.python.org/3/library/multiprocessing.html#programming-guidelines
# TODO: queue maxsize, or prefrabily some sort of throttled queue (like zmq hight water mark)
q_webcam1 = Queue(maxsize=1)
q_webcam2 = Queue(maxsize=1)
q_webcam3 = Queue(maxsize=1)
q_webcam4 = Queue(maxsize=1)
q_process1 = Queue(maxsize=1)
q_process2 = Queue(maxsize=1)
q_process3 = Queue(maxsize=1)
p1 = Process(target=record, args=(camera_id, q_webcam1, q_webcam2,q_webcam3,q_webcam4))
p2 = Process(target=display, args=(image_size, q_webcam1, q_process1, q_process2, q_process3 ))
p3 = Process(target=process1_hog, args=(q_webcam2, q_process1,))
p4 = Process(target=process2_dnn, args=(q_webcam3, q_process2,))
p5 = Process(target=process3_haar, args=(q_webcam4, q_process3,))
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p2.join() # process with the display interface
p1.kill()
p3.kill()
p4.kill()
p5.kill()

256
face_recognition/hog.py

@ -0,0 +1,256 @@ @@ -0,0 +1,256 @@
import numpy as np
from skimage.feature import _hoghistogram
from skimage.feature._hog import _hog_normalize_block, _hog_channel_gradient
def hog(image, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(3, 3),
block_norm='L2-Hys', visualize=False, transform_sqrt=False,
feature_vector=True, multichannel=None, visualize_factor=1.):
"""Extract Histogram of Oriented Gradients (HOG) for a given image.
Compute a Histogram of Oriented Gradients (HOG) by
1. (optional) global image normalization
2. computing the gradient image in `row` and `col`
3. computing gradient histograms
4. normalizing across blocks
5. flattening into a feature vector
Parameters
----------
image : (M, N[, C]) ndarray
Input image.
orientations : int, optional
Number of orientation bins.
pixels_per_cell : 2-tuple (int, int), optional
Size (in pixels) of a cell.
cells_per_block : 2-tuple (int, int), optional
Number of cells in each block.
block_norm : str {'L1', 'L1-sqrt', 'L2', 'L2-Hys'}, optional
Block normalization method:
``L1``
Normalization using L1-norm.
``L1-sqrt``
Normalization using L1-norm, followed by square root.
``L2``
Normalization using L2-norm.
``L2-Hys``
Normalization using L2-norm, followed by limiting the
maximum values to 0.2 (`Hys` stands for `hysteresis`) and
renormalization using L2-norm. (default)
For details, see [3]_, [4]_.
visualize : bool, optional
Also return an image of the HOG. For each cell and orientation bin,
the image contains a line segment that is centered at the cell center,
is perpendicular to the midpoint of the range of angles spanned by the
orientation bin, and has intensity proportional to the corresponding
histogram value.
transform_sqrt : bool, optional
Apply power law compression to normalize the image before
processing. DO NOT use this if the image contains negative
values. Also see `notes` section below.
feature_vector : bool, optional
Return the data as a feature vector by calling .ravel() on the result
just before returning.
multichannel : boolean, optional
If True, the last `image` dimension is considered as a color channel,
otherwise as spatial.
Returns
-------
out : (n_blocks_row, n_blocks_col, n_cells_row, n_cells_col, n_orient) ndarray
HOG descriptor for the image. If `feature_vector` is True, a 1D
(flattened) array is returned.
hog_image : (M, N) ndarray, optional
A visualisation of the HOG image. Only provided if `visualize` is True.
References
----------
.. [1] https://en.wikipedia.org/wiki/Histogram_of_oriented_gradients
.. [2] Dalal, N and Triggs, B, Histograms of Oriented Gradients for
Human Detection, IEEE Computer Society Conference on Computer
Vision and Pattern Recognition 2005 San Diego, CA, USA,
https://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf,
:DOI:`10.1109/CVPR.2005.177`
.. [3] Lowe, D.G., Distinctive image features from scale-invatiant
keypoints, International Journal of Computer Vision (2004) 60: 91,
http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf,
:DOI:`10.1023/B:VISI.0000029664.99615.94`
.. [4] Dalal, N, Finding People in Images and Videos,
Human-Computer Interaction [cs.HC], Institut National Polytechnique
de Grenoble - INPG, 2006,
https://tel.archives-ouvertes.fr/tel-00390303/file/NavneetDalalThesis.pdf
Notes
-----
The presented code implements the HOG extraction method from [2]_ with
the following changes: (I) blocks of (3, 3) cells are used ((2, 2) in the
paper); (II) no smoothing within cells (Gaussian spatial window with sigma=8pix
in the paper); (III) L1 block normalization is used (L2-Hys in the paper).
Power law compression, also known as Gamma correction, is used to reduce
the effects of shadowing and illumination variations. The compression makes
the dark regions lighter. When the kwarg `transform_sqrt` is set to
``True``, the function computes the square root of each color channel
and then applies the hog algorithm to the image.
"""
image = np.atleast_2d(image)
if multichannel is None:
multichannel = (image.ndim == 3)
ndim_spatial = image.ndim - 1 if multichannel else image.ndim
if ndim_spatial != 2:
raise ValueError('Only images with 2 spatial dimensions are '
'supported. If using with color/multichannel '
'images, specify `multichannel=True`.')
"""
The first stage applies an optional global image normalization
equalisation that is designed to reduce the influence of illumination
effects. In practice we use gamma (power law) compression, either
computing the square root or the log of each color channel.
Image texture strength is typically proportional to the local surface
illumination so this compression helps to reduce the effects of local
shadowing and illumination variations.
"""
if transform_sqrt:
image = np.sqrt(image)
"""
The second stage computes first order image gradients. These capture
contour, silhouette and some texture information, while providing
further resistance to illumination variations. The locally dominant
color channel is used, which provides color invariance to a large
extent. Variant methods may also include second order image derivatives,
which act as primitive bar detectors - a useful feature for capturing,
e.g. bar like structures in bicycles and limbs in humans.
"""
if image.dtype.kind == 'u':
# convert uint image to float
# to avoid problems with subtracting unsigned numbers
image = image.astype('float')
if multichannel:
g_row_by_ch = np.empty_like(image, dtype=np.double)
g_col_by_ch = np.empty_like(image, dtype=np.double)
g_magn = np.empty_like(image, dtype=np.double)
for idx_ch in range(image.shape[2]):
g_row_by_ch[:, :, idx_ch], g_col_by_ch[:, :, idx_ch] = \
_hog_channel_gradient(image[:, :, idx_ch])
g_magn[:, :, idx_ch] = np.hypot(g_row_by_ch[:, :, idx_ch],
g_col_by_ch[:, :, idx_ch])
# For each pixel select the channel with the highest gradient magnitude
idcs_max = g_magn.argmax(axis=2)
rr, cc = np.meshgrid(np.arange(image.shape[0]),
np.arange(image.shape[1]),
indexing='ij',
sparse=True)
g_row = g_row_by_ch[rr, cc, idcs_max]
g_col = g_col_by_ch[rr, cc, idcs_max]
else:
g_row, g_col = _hog_channel_gradient(image)
"""
The third stage aims to produce an encoding that is sensitive to
local image content while remaining resistant to small changes in
pose or appearance. The adopted method pools gradient orientation
information locally in the same way as the SIFT [Lowe 2004]
feature. The image window is divided into small spatial regions,
called "cells". For each cell we accumulate a local 1-D histogram
of gradient or edge orientations over all the pixels in the
cell. This combined cell-level 1-D histogram forms the basic
"orientation histogram" representation. Each orientation histogram
divides the gradient angle range into a fixed number of
predetermined bins. The gradient magnitudes of the pixels in the
cell are used to vote into the orientation histogram.
"""
s_row, s_col = image.shape[:2]
c_row, c_col = pixels_per_cell
b_row, b_col = cells_per_block
n_cells_row = int(s_row // c_row) # number of cells along row-axis
n_cells_col = int(s_col // c_col) # number of cells along col-axis
# compute orientations integral images
orientation_histogram = np.zeros((n_cells_row, n_cells_col, orientations))
_hoghistogram.hog_histograms(g_col, g_row, c_col, c_row, s_col, s_row,
n_cells_col, n_cells_row,
orientations, orientation_histogram)
# now compute the histogram for each cell
hog_image = None
if visualize:
from skimage import draw
radius = min(c_row * visualize_factor, c_col * visualize_factor) // 2 - 1
orientations_arr = np.arange(orientations)
# set dr_arr, dc_arr to correspond to midpoints of orientation bins
orientation_bin_midpoints = (
np.pi * (orientations_arr + .5) / orientations)
dr_arr = radius * np.sin(orientation_bin_midpoints)
dc_arr = radius * np.cos(orientation_bin_midpoints)
hog_image = np.zeros((
int(s_row * visualize_factor), int(s_col * visualize_factor)
), dtype=float)
for r in range(n_cells_row):
for c in range(n_cells_col):
for o, dr, dc in zip(orientations_arr, dr_arr, dc_arr):
centre = tuple([r * c_row * visualize_factor + c_row * visualize_factor // 2,
c * c_col * visualize_factor + c_col * visualize_factor // 2])
rr, cc = draw.line(int(centre[0] - dc),
int(centre[1] + dr),
int(centre[0] + dc),
int(centre[1] - dr))
hog_image[rr, cc] += orientation_histogram[r, c, o]
"""
The fourth stage computes normalization, which takes local groups of
cells and contrast normalizes their overall responses before passing
to next stage. Normalization introduces better invariance to illumination,
shadowing, and edge contrast. It is performed by accumulating a measure
of local histogram "energy" over local groups of cells that we call
"blocks". The result is used to normalize each cell in the block.
Typically each individual cell is shared between several blocks, but
its normalizations are block dependent and thus different. The cell
thus appears several times in the final output vector with different
normalizations. This may seem redundant but it improves the performance.
We refer to the normalized block descriptors as Histogram of Oriented
Gradient (HOG) descriptors.
"""
n_blocks_row = (n_cells_row - b_row) + 1
n_blocks_col = (n_cells_col - b_col) + 1
normalized_blocks = np.zeros((n_blocks_row, n_blocks_col,
b_row, b_col, orientations))
for r in range(n_blocks_row):
for c in range(n_blocks_col):
block = orientation_histogram[r:r + b_row, c:c + b_col, :]
normalized_blocks[r, c, :] = \
_hog_normalize_block(block, method=block_norm)
"""
The final step collects the HOG descriptors from all blocks of a dense
overlapping grid of blocks covering the detection window into a combined
feature vector for use in the window classifier.
"""
if feature_vector:
normalized_blocks = normalized_blocks.ravel()
if visualize:
return normalized_blocks, hog_image
else:
return normalized_blocks

20719
haarcascade_frontalface_alt2.xml

File diff suppressed because it is too large Load Diff

55
hog_test.py

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
import matplotlib.pyplot as plt
import time
from skimage.feature import hog
from skimage import data, exposure
import face_recognition
import cv2
image = data.astronaut()
image = face_recognition.load_image_file("testimage.png")
face_location = face_recognition.face_locations(image)
# print(image)
fd, hog_image = hog(image, orientations=8, pixels_per_cell=(16, 16),
cells_per_block=(1, 1), visualize=True, multichannel=True)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), sharex=True, sharey=True)
ax1.axis('off')
ax1.imshow(image, cmap=plt.cm.gray)
ax1.set_title('Input image')
# Rescale histogram for better display
hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 10))
ax2.axis('off')
ax2.imshow(hog_image_rescaled, cmap=plt.cm.gray)
ax2.set_title('Histogram of Oriented Gradients')
plt.show()
print('done')
# # Display the results
# (top, right, bottom, left) = face_location[0]
# # Scale back up face locations since the frame we detected in was scaled to 1/4 size
# top *= 4
# right *= 4
# bottom *= 4
# left *= 4
# # Draw a box around the face
# cv2.rectangle(image, (left, top), (right, bottom), (0, 0, 255), 2)
# # Draw a label with a name below the face
# cv2.rectangle(image, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
# font = cv2.FONT_HERSHEY_DUPLEX
# cv2.putText(image, '...', (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
# # Display the resulting image
# cv2.imshow('Video', image)
# time.sleep(10)

99
live_dnn.py

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
# import face_recognition
import cv2
from skimage.feature import hog
from skimage import data, exposure
import matplotlib.pyplot as plt
import numpy as np
import dlib
import logging
import time
imagefile = "Marjo.jpg"
prototxt = "dnn/face_detector/opencv_face_detector.pbtxt"
prototxt = "dnn/face_detector/deploy.prototxt"
model = "dnn/face_detector/res10_300x300_ssd_iter_140000_fp16.caffemodel"
confidence_threshold = .0
logger = logging.getLogger('dnn')
image = cv2.imread(imagefile)
# rows = open(args["labels"]).read().strip().split("\n")
# classes = [r[r.find(" ") + 1:].split(",")[0] for r in rows]
logger.info("[INFO] loding model...")
net = cv2.dnn.readNetFromCaffe(prototxt, model)
logger.info("Loaded")
video_capture = cv2.VideoCapture(2)
while True:
# Grab a single frame of video
ret, image = video_capture.read()
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
net.setInput(blob)
start = time.time()
detections = net.forward()
end = time.time()
logger.debug(f"classification took {end-start:.5} seconds")
# idxs = np.argsort(detections[0])[::-1][:5]
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
# compute the (x, y)-coordinates of the bounding box for the
# object
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
# we always draw
# First we crop the sub-rect from the image
sub_img = image[startY:endY, startX:endX]
rect_img = sub_img.copy()
width = 2
cv2.rectangle(rect_img, (0, 0),
(sub_img.shape[1]-int(width/2), sub_img.shape[0]-int(width/2)),
(0, 0, 255), width)
# white_rect = np.ones(sub_img.shape, dtype=np.uint8) * 255
# At least 10% opacity
alpha = max(.1, confidence)
res = cv2.addWeighted(sub_img, 1-alpha, rect_img, alpha, 1.0)
# Putting the image back to its position
image[startY:endY, startX:endX] = res
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > confidence_threshold:
# draw the bounding box of the face along with the associated
# probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
# cv2.rectangle(image, (startX, startY), (endX, endY),
# (0, 0, 255), 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
# show the output image
cv2.imshow("Output", image)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()

71
live_hog.py

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
# import face_recognition
import cv2
from skimage.feature import hog
from skimage import data, exposure
import matplotlib.pyplot as plt
import numpy as np
import dlib
# This is a demo of running face recognition on live video from your webcam. It's a little more complicated than the
# other example, but it includes some basic performance tweaks to make things run a lot faster:
# 1. Process each video frame at 1/4 resolution (though still display it at full resolution)
# 2. Only detect faces in every other frame of video.
# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam.
# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this
# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead.
# Get a reference to webcam #0 (the default one)
video_capture = cv2.VideoCapture(2)
face_detector = dlib.get_frontal_face_detector()
process_this_frame = True
while True:
if process_this_frame:
# Grab a single frame of video
ret, frame = video_capture.read()
small_frame = cv2.resize(frame, (0, 0), fx=0.7, fy=0.7)
fd, hog_image = hog(small_frame, orientations=8, pixels_per_cell=(16, 16),
cells_per_block=(1, 1), visualize=True, multichannel=True)
hog_image_rescaled = exposure.rescale_intensity(hog_image, in_range=(0, 15))
# Resize frame of video to 1/4 size for faster face recognition processing
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
rgb_small_frame = small_frame[:, :, ::-1]
dets, scores, idxs = face_detector.run(rgb_small_frame, 1, -1)
print(dets, scores, idxs)
# Display the results
for i, rectangle in enumerate(dets):
probability = scores[i]
print(rectangle)
# Scale back up face locations since the frame we detected in was scaled to 1/4 size
top = rectangle.top() #* 4
right = rectangle.right() #* 4
bottom = rectangle.bottom() #* 4
left = rectangle.left() #* 4
brightness = (probability + 1)/3
# Draw a box around the face
cv2.rectangle(hog_image_rescaled, (left, top), (right, bottom), brightness, 2)
# # Draw a label with a name below the face
# cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
# Display the resulting image
cv2.imshow('Video', hog_image_rescaled)
process_this_frame = not process_this_frame
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()

10
mirror.py

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
import argparse
import face_recognition.comparison
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Visualise face recognition algorithms.')
parser.add_argument('--camera', '-c', type=int, default=0,
help='Numeric id of the camera')
args = parser.parse_args()
face_recognition.comparison.main(args.camera)

20
recognition_test.py

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
from PIL import Image
import face_recognition
image = face_recognition.load_image_file("testimage.png")
face_locations = face_recognition.face_locations(image)
print("I found {} face(s) in this photograph.".format(len(face_locations)))
for face_location in face_locations:
# Print the location of each face in this image
top, right, bottom, left = face_location
print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))
# You can access the actual face itself like this:
face_image = image[top:bottom, left:right]
pil_image = Image.fromarray(face_image)
pil_image.show()

4
requirements.txt

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
scipy
numpy
dlib
Pillow

79
test_rec.py

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
import face_recognition
import cv2
import numpy as np
# This is a super simple (but slow) example of running face recognition on live video from your webcam.
# There's a second example that's a little more complicated but runs faster.
# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam.
# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this
# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead.
# Get a reference to webcam #0 (the default one)
video_capture = cv2.VideoCapture(2)
# Load a sample picture and learn how to recognize it.
Ruben_image = face_recognition.load_image_file("Ruben.jpg")
Ruben_face_encoding = face_recognition.face_encodings(Ruben_image)[0]
# Load a second samp=le picture and learn how to recognize it.
Marjo_image = face_recognition.load_image_file("Marjo2.jpg")
Marjo_face_encoding = face_recognition.face_encodings(Marjo_image)[0]
# Create arrays of known face encodings and their names
known_face_encodings = [
Ruben_face_encoding,
Marjo_face_encoding
]
known_face_names = [
"Ruben",
"Marjo"
]
while True:
# Grab a single frame of video
ret, frame = video_capture.read()
# Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
rgb_frame = frame[:, :, ::-1]
# Find all the faces and face enqcodings in the frame of video
face_locations = face_recognition.face_locations(rgb_frame)
face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
# Loop through each face in this frame of video
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
# See if the face is a match for the known face(s)
matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
name = "Unknown"
# If a match was found in known_face_encodings, just use the first one.
# if True in matches:
# first_match_index = matches.index(True)
# name = known_face_names[first_match_index]
# Or instead, use the known face with the smallest distance to the new face
face_distances = face_recognition.face_distance(known_face_encodings, face_encoding)
best_match_index = np.argmin(face_distances)
if matches[best_match_index]:
name = known_face_names[best_match_index]
# Draw a box around the face
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
# Draw a label with a name below the face
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
# Display the resulting image
cv2.imshow('Video', frame)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# Release handle to the webcam
video_capture.release()
cv2.destroyAllWindows()

89
test_rust.py

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
from cffi import FFI
from PIL import Image
import numpy as np
import cv2, time
ffi = FFI()
ffi.cdef("""
int test(int);
typedef void* haarclassifier;
haarclassifier classifier_new();
void scan_image(haarclassifier, size_t width,size_t height, char *input, char *buffer, size_t length, bool debug);
""")
C = ffi.dlopen("/home/ruben/Documents/Projecten/2020/rust/testproject/target/debug/libvisual_haarcascades_lib.so")
print(C.test(9))
# i = Image.open("/home/ruben/Documents/Projecten/2020/rust/lena_orig.png")
# a= np.array(i)
a= cv2.imread("/home/ruben/Documents/Projecten/2020/rust/lena_orig.png")
capture = cv2.VideoCapture(2)
print("Buffer", capture.get(cv2.CAP_PROP_BUFFERSIZE))
capture.set(cv2.CAP_PROP_BUFFERSIZE, 1)
while True:
ret, a = capture.read()
print(a.shape)
# i = Image.open("Marjo.jpg")
width = int(a.shape[1]/4)
height = int(a.shape[0]/4)
image = cv2.resize(a, (width,height))
pixel_format = "RGB" #The raytracer only supports one format
bytes_per_pixel = 3
buffer_len = width * height * bytes_per_pixel
buffer = ffi.new("char[]", buffer_len)
# buffer2 = ffi.from_buffer("char[]", (i.tobytes("raw","RGB")))
buffer2 = ffi.from_buffer("char[]", image.tobytes())
haar = C.classifier_new()
# i = Image.open("/home/ruben/Documents/Projecten/2020/rust/lena_orig.png")
# data = i.tobytes("raw", "RGB")
print('scan!')
start=time.time()
C.scan_image(haar, width, height, buffer2, buffer, buffer_len, True)
print(f"scanned in {time.time() - start}s", buffer)
# img = Image.frombuffer(pixel_format, (width, height), ffi.buffer(buffer),
# "raw", pixel_format, 0, 1)
# img = Image.frombuffer(pixel_format, (width, height), ffi.buffer(buffer),
# "raw", pixel_format, 0, 1)
img = Image.frombuffer(pixel_format, (width, height), ffi.buffer(buffer),
"raw", pixel_format, 0, 1)
a= np.array(img)
# a= np.frombuffer(ffi.buffer(buffer))
# a.reshape((height, width, bytes_per_pixel))
a = a[:, :, ::-1]
img_concate_Verti1 = np.concatenate((image,a),axis=0)
cv2.imshow("image",img_concate_Verti1)
# Hit 'q' on the keyboard to quit!
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# img.show()
# class Scene(object):
# def __init__(self, width, height, fov, shadow_bias, max_recursion_depth):
# self.__width = width