Skip to content

Commit 33299ce

Browse files
authored
Merge pull request #75 from HyperInspire/dev/cuda
Dev/cuda Former-commit-id: 87377ab
2 parents 26916f1 + 86816f9 commit 33299ce

File tree

3 files changed

+106
-37
lines changed

3 files changed

+106
-37
lines changed

command/build_linux_cuda.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ cmake -DCMAKE_SYSTEM_NAME=Linux \
4141
-DISF_BUILD_WITH_SAMPLE=ON \
4242
-DISF_BUILD_WITH_TEST=ON \
4343
-DISF_ENABLE_BENCHMARK=ON \
44-
-DISF_ENABLE_USE_LFW_DATA=ON \
45-
-DISF_ENABLE_TEST_EVALUATION=ON \
44+
-DISF_ENABLE_USE_LFW_DATA=OFF \
45+
-DISF_ENABLE_TEST_EVALUATION=OFF \
46+
-DISF_ENABLE_TRACKING_BY_DETECTION=ON \
4647
-DMNN_CUDA=ON \
4748
-DISF_GLOBAL_INFERENCE_BACKEND_USE_MNN_CUDA=ON \
4849
-DISF_LINUX_MNN_CUDA=/home/tunm/softwate/MNN-2.7.2/build_cuda ${SCRIPT_DIR}

cpp/sample/cpp/sample_face_track_video.cpp

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#include "c_api/intypedef.h"
33
#include "opencv2/opencv.hpp"
44
#include "inspireface/c_api/inspireface.h"
5+
#include <unordered_map>
6+
#include <functional>
57

68
void drawMode(cv::Mat& frame, HFDetectMode mode) {
79
std::string modeText;
@@ -19,9 +21,26 @@ void drawMode(cv::Mat& frame, HFDetectMode mode) {
1921
modeText = "Mode: Unknown";
2022
break;
2123
}
22-
cv::putText(frame, modeText, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(255, 255, 255), 2);
24+
cv::putText(frame, modeText, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(90, 100, 255), 2);
2325
}
2426

27+
cv::Scalar generateColor(int id) {
28+
int maxID = 100;
29+
id = id % maxID;
30+
31+
int hue = (id * 360 / maxID) % 360;
32+
int saturation = 255;
33+
int value = 200;
34+
35+
cv::Mat hsv(1, 1, CV_8UC3, cv::Scalar(hue, saturation, value));
36+
cv::Mat rgb;
37+
cv::cvtColor(hsv, rgb, cv::COLOR_HSV2BGR);
38+
39+
cv::Vec3b rgbColor = rgb.at<cv::Vec3b>(0, 0);
40+
return cv::Scalar(rgbColor[0], rgbColor[1], rgbColor[2]);
41+
}
42+
43+
2544
int main(int argc, char* argv[]) {
2645
// Check whether the number of parameters is correct
2746
if (argc != 3) {
@@ -46,11 +65,11 @@ int main(int argc, char* argv[]) {
4665
// Enable the functions in the pipeline: mask detection, live detection, and face quality detection
4766
HOption option = HF_ENABLE_QUALITY | HF_ENABLE_MASK_DETECT | HF_ENABLE_INTERACTION;
4867
// Video or frame sequence mode uses VIDEO-MODE, which is face detection with tracking
49-
HFDetectMode detMode = HF_DETECT_MODE_LIGHT_TRACK;
68+
HFDetectMode detMode = HF_DETECT_MODE_TRACK_BY_DETECTION;
5069
// Maximum number of faces detected
5170
HInt32 maxDetectNum = 20;
5271
// Face detection image input level
53-
HInt32 detectPixelLevel = 160;
72+
HInt32 detectPixelLevel = 640;
5473
// fps in tracking-by-detection mode
5574
HInt32 trackByDetectFps = 20;
5675
HFSession session = {0};
@@ -122,35 +141,36 @@ int main(int argc, char* argv[]) {
122141

123142
// Draw detection mode on the frame
124143
drawMode(draw, detMode);
125-
if (faceNum > 0) {
126-
ret = HFMultipleFacePipelineProcessOptional(session, imageHandle, &multipleFaceData, option);
127-
if (ret != HSUCCEED)
128-
{
129-
std::cout << "HFMultipleFacePipelineProcessOptional error: " << ret << std::endl;
130-
return ret;
131-
}
132-
HFFaceIntereactionResult result;
133-
ret = HFGetFaceIntereactionResult(session, &result);
134-
if (ret != HSUCCEED)
135-
{
136-
std::cout << "HFGetFaceIntereactionResult error: " << ret << std::endl;
137-
return ret;
138-
}
139-
std::cout << "Left eye status: " << result.leftEyeStatusConfidence[0] << std::endl;
140-
std::cout << "Righ eye status: " << result.rightEyeStatusConfidence[0] << std::endl;
141-
142-
}
144+
// if (faceNum > 0) {
145+
// ret = HFMultipleFacePipelineProcessOptional(session, imageHandle, &multipleFaceData, option);
146+
// if (ret != HSUCCEED)
147+
// {
148+
// std::cout << "HFMultipleFacePipelineProcessOptional error: " << ret << std::endl;
149+
// return ret;
150+
// }
151+
// HFFaceIntereactionResult result;
152+
// ret = HFGetFaceIntereactionResult(session, &result);
153+
// if (ret != HSUCCEED)
154+
// {
155+
// std::cout << "HFGetFaceIntereactionResult error: " << ret << std::endl;
156+
// return ret;
157+
// }
158+
// std::cout << "Left eye status: " << result.leftEyeStatusConfidence[0] << std::endl;
159+
// std::cout << "Righ eye status: " << result.rightEyeStatusConfidence[0] << std::endl;
160+
161+
// }
143162

144163
for (int index = 0; index < faceNum; ++index) {
145164
// std::cout << "========================================" << std::endl;
146165
// std::cout << "Process face index: " << index << std::endl;
166+
// Print FaceID, In VIDEO-MODE it is fixed, but it may be lost
167+
auto trackId = multipleFaceData.trackIds[index];
168+
147169
// Use OpenCV's Rect to receive face bounding boxes
148170
auto rect = cv::Rect(multipleFaceData.rects[index].x, multipleFaceData.rects[index].y,
149171
multipleFaceData.rects[index].width, multipleFaceData.rects[index].height);
150-
cv::rectangle(draw, rect, cv::Scalar(0, 100, 255), 5);
172+
cv::rectangle(draw, rect, generateColor(trackId), 3);
151173

152-
// Print FaceID, In VIDEO-MODE it is fixed, but it may be lost
153-
auto trackId = multipleFaceData.trackIds[index];
154174
// std::cout << "FaceID: " << trackId << std::endl;
155175

156176
// Print Head euler angle, It can often be used to judge the quality of a face by the Angle of the head
@@ -160,7 +180,7 @@ int main(int argc, char* argv[]) {
160180

161181
// Add TrackID to the drawing
162182
cv::putText(draw, "ID: " + std::to_string(trackId), cv::Point(rect.x, rect.y - 10),
163-
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);
183+
cv::FONT_HERSHEY_SIMPLEX, 0.5, generateColor(trackId), 2);
164184

165185
HInt32 numOfLmk;
166186
HFGetNumOfFaceDenseLandmark(&numOfLmk);
@@ -172,7 +192,7 @@ int main(int argc, char* argv[]) {
172192
}
173193
for (size_t i = 0; i < numOfLmk; i++) {
174194
cv::Point2f p(denseLandmarkPoints[i].x, denseLandmarkPoints[i].y);
175-
cv::circle(draw, p, 0, (0, 0, 255), 2);
195+
cv::circle(draw, p, 0, generateColor(trackId), 2);
176196
}
177197
}
178198

python/sample_face_track_from_video.py

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,36 @@
44
from inspireface.param import *
55
import numpy as np
66

7+
8+
def generate_color(id):
9+
"""
10+
Generate a bright color based on the given integer ID. Ensures 50 unique colors.
11+
12+
Args:
13+
id (int): The ID for which to generate a color.
14+
15+
Returns:
16+
tuple: A tuple representing the color in BGR format.
17+
"""
18+
max_id = 50 # Number of unique colors
19+
id = id % max_id
20+
21+
# Generate HSV color
22+
hue = int((id * 360 / max_id) % 360) # Distribute hue values equally
23+
saturation = 200 + (55 * id) % 55 # High saturation for bright colors
24+
value = 200 + (55 * id) % 55 # High value for bright colors
25+
26+
hsv_color = np.uint8([[[hue, saturation, value]]])
27+
rgb_color = cv2.cvtColor(hsv_color, cv2.COLOR_HSV2BGR)[0][0]
28+
29+
return (int(rgb_color[0]), int(rgb_color[1]), int(rgb_color[2]))
30+
731
@click.command()
832
@click.argument("resource_path")
933
@click.argument('source')
1034
@click.option('--show', is_flag=True, help='Display the video stream or video file in a window.')
11-
def case_face_tracker_from_video(resource_path, source, show):
35+
@click.option('--out', type=str, default=None, help='Path to save the processed video.')
36+
def case_face_tracker_from_video(resource_path, source, show, out):
1237
"""
1338
Launch a face tracking process from a video source. The 'source' can either be a webcam index (0, 1, ...)
1439
or a path to a video file. Use the --show option to display the video.
@@ -17,6 +42,7 @@ def case_face_tracker_from_video(resource_path, source, show):
1742
resource_path (str): Path to the resource directory for face tracking algorithms.
1843
source (str): Webcam index or path to the video file.
1944
show (bool): If set, the video will be displayed in a window.
45+
out (str): Path to save the processed video.
2046
"""
2147
# Initialize the face tracker or other resources.
2248
print(f"Initializing with resources from: {resource_path}")
@@ -26,8 +52,8 @@ def case_face_tracker_from_video(resource_path, source, show):
2652

2753
# Optional features, loaded during session creation based on the modules specified.
2854
opt = HF_ENABLE_NONE
29-
session = ifac.InspireFaceSession(opt, HF_DETECT_MODE_LIGHT_TRACK) # Use video mode
30-
55+
session = ifac.InspireFaceSession(opt, HF_DETECT_MODE_TRACK_BY_DETECTION, max_detect_num=25, detect_pixel_level=640) # Use video mode
56+
session.set_filter_minimum_face_pixel_size(0)
3157
# Determine if the source is a digital webcam index or a video file path.
3258
try:
3359
source_index = int(source) # Try to convert source to an integer.
@@ -42,6 +68,15 @@ def case_face_tracker_from_video(resource_path, source, show):
4268
print("Error: Could not open video source.")
4369
return
4470

71+
# VideoWriter to save the processed video if out is provided.
72+
if out:
73+
fourcc = cv2.VideoWriter_fourcc(*'XVID')
74+
fps = cap.get(cv2.CAP_PROP_FPS) if cap.get(cv2.CAP_PROP_FPS) > 0 else 30
75+
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
76+
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
77+
out_video = cv2.VideoWriter(out, fourcc, fps, (frame_width, frame_height))
78+
print(f"Saving video to: {out}")
79+
4580
# Main loop to process video frames.
4681
while True:
4782
ret, frame = cap.read()
@@ -62,31 +97,44 @@ def case_face_tracker_from_video(resource_path, source, show):
6297
# Calculate center, size, and angle
6398
center = ((x1 + x2) / 2, (y1 + y2) / 2)
6499
size = (x2 - x1, y2 - y1)
65-
angle = face.roll
66-
67-
# Get rotation matrix
68-
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
100+
angle = face.roll
69101

70102
# Apply rotation to the bounding box corners
71103
rect = ((center[0], center[1]), (size[0], size[1]), angle)
72104
box = cv2.boxPoints(rect)
73105
box = box.astype(int)
74106

107+
color = generate_color(face.track_id)
108+
75109
# Draw the rotated bounding box
76-
cv2.drawContours(frame, [box], 0, (100, 180, 29), 2)
110+
cv2.drawContours(frame, [box], 0, color, 4)
77111

78112
# Draw landmarks
79113
lmk = session.get_face_dense_landmark(face)
80114
for x, y in lmk.astype(int):
81-
cv2.circle(frame, (x, y), 0, (220, 100, 0), 2)
115+
cv2.circle(frame, (x, y), 0, color, 4)
116+
117+
# Draw track ID at the top of the bounding box
118+
text = f"ID: {face.track_id}"
119+
text_size, _ = cv2.getTextSize(text, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 2)
120+
text_x = min(box[:, 0])
121+
text_y = min(box[:, 1]) - 10
122+
if text_y < 0:
123+
text_y = min(box[:, 1]) + text_size[1] + 10
124+
cv2.putText(frame, text, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
82125

83126
if show:
84127
cv2.imshow("Face Tracker", frame)
85128
if cv2.waitKey(1) & 0xFF == ord('q'):
86129
break # Exit loop if 'q' is pressed.
87130

131+
if out:
132+
out_video.write(frame)
133+
88134
# Cleanup: release video capture and close any open windows.
89135
cap.release()
136+
if out:
137+
out_video.release()
90138
cv2.destroyAllWindows()
91139
print("Released all resources and closed windows.")
92140

0 commit comments

Comments
 (0)