Skip to content

Commit e669c3d

Browse files
committed
update 2.5.4
1 parent 3e916c8 commit e669c3d

File tree

16 files changed

+3705
-339
lines changed

16 files changed

+3705
-339
lines changed
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
{
22
"name": "EnoxSoftware.OpenCVForUnity",
33
"references": [],
4-
"optionalUnityReferences": [],
54
"includePlatforms": [],
65
"excludePlatforms": [],
76
"allowUnsafeCode": false,
87
"overrideReferences": false,
98
"precompiledReferences": [],
109
"autoReferenced": true,
11-
"defineConstraints": []
10+
"defineConstraints": [],
11+
"versionDefines": [],
12+
"noEngineReferences": false
1213
}

Assets/OpenCVForUnity/Examples/MainModules/dnn/HandPoseEstimationExample/HandPoseEstimationExample.cs

Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,12 +2796,15 @@ private class HandPoseEstimator
27962796
//int[] PALM_LANDMARK_IDS = new int[] { 0, 5, 9, 13, 17, 1, 2 };
27972797
int PALM_LANDMARKS_INDEX_OF_PALM_BASE = 0;
27982798
int PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE = 2;
2799+
Point PALM_BOX_PRE_SHIFT_VECTOR = new Point(0, 0);
2800+
//double PALM_BOX_PRE_ENLARGE_FACTOR = 4.0;
27992801
Point PALM_BOX_SHIFT_VECTOR = new Point(0, -0.4);
28002802
double PALM_BOX_ENLARGE_FACTOR = 3.0;
28012803
Point HAND_BOX_SHIFT_VECTOR = new Point(0, -0.1);
28022804
double HAND_BOX_ENLARGE_FACTOR = 1.65;
28032805

28042806
Mat tmpImage;
2807+
Mat tmpRotatedImage;
28052808

28062809
public HandPoseEstimator(string modelFilepath, float confThreshold = 0.8f, int backend = Dnn.DNN_BACKEND_OPENCV, int target = Dnn.DNN_TARGET_CPU)
28072810
{
@@ -2819,12 +2822,54 @@ public HandPoseEstimator(string modelFilepath, float confThreshold = 0.8f, int b
28192822
handpose_estimation_net.setPreferableTarget(this.target);
28202823
}
28212824

2822-
protected virtual Mat preprocess(Mat image, Mat palm, out Mat rotated_palm_bbox, out double angle, out Mat rotation_matrix)
2825+
protected virtual Mat preprocess(Mat image, Mat palm, out Mat rotated_palm_bbox, out double angle, out Mat rotation_matrix, out Mat pad_bias)
28232826
{
2827+
// '''
2828+
// Rotate input for inference.
2829+
// Parameters:
2830+
// image - input image of BGR channel order
2831+
// palm_bbox - palm bounding box found in image of format[[x1, y1], [x2, y2]] (top - left and bottom - right points)
2832+
// palm_landmarks - 7 landmarks(5 finger base points, 2 palm base points) of shape[7, 2]
2833+
// Returns:
2834+
// rotated_hand - rotated hand image for inference
2835+
// rotate_palm_bbox - palm box of interest range
2836+
// angle - rotate angle for hand
2837+
// rotation_matrix - matrix for rotation and de - rotation
2838+
// pad_bias - pad pixels of interest range
2839+
// '''
2840+
2841+
// Generate an image with padding added after the squarify process.
2842+
int maxSize = Math.Max(image.width(), image.height());
2843+
int tmpImageSize = (int)(maxSize * 1.5);
2844+
if (tmpImage != null && (tmpImage.width() != tmpImageSize || tmpImage.height() != tmpImageSize))
2845+
{
2846+
tmpImage.Dispose();
2847+
tmpImage = null;
2848+
tmpRotatedImage.Dispose();
2849+
tmpRotatedImage = null;
2850+
}
2851+
if (tmpImage == null)
2852+
{
2853+
tmpImage = new Mat(tmpImageSize, tmpImageSize, image.type(), Scalar.all(0));
2854+
tmpRotatedImage = tmpImage.clone();
2855+
}
2856+
2857+
int pad = (tmpImageSize - maxSize) / 2;
2858+
pad_bias = new Mat(2, 1, CvType.CV_32FC1);
2859+
pad_bias.put(0, 0, new float[] { -pad, -pad });
2860+
2861+
Mat _tmpImage_roi = new Mat(tmpImage, new OpenCVRect(pad, pad, image.width(), image.height()));
2862+
image.copyTo(_tmpImage_roi);
2863+
2864+
// Apply the pad_bias to palm_bbox and palm_landmarks.
2865+
Mat new_palm = palm.clone();
2866+
Mat palm_bbox_and_landmark = new_palm.colRange(new OpenCVRange(0, 18)).reshape(2, 9);
2867+
Core.add(palm_bbox_and_landmark, new Scalar(pad, pad), palm_bbox_and_landmark);
2868+
28242869
// Rotate input to have vertically oriented hand image
28252870
// compute rotation
2826-
Mat palm_bbox = palm.colRange(new OpenCVRange(0, 4)).reshape(1, 2);
2827-
Mat palm_landmarks = palm.colRange(new OpenCVRange(4, 18)).reshape(1, 7);
2871+
Mat palm_bbox = new_palm.colRange(new OpenCVRange(0, 4)).reshape(1, 2);
2872+
Mat palm_landmarks = new_palm.colRange(new OpenCVRange(4, 18)).reshape(1, 7);
28282873

28292874
Mat p1 = palm_landmarks.row(PALM_LANDMARKS_INDEX_OF_PALM_BASE);
28302875
Mat p2 = palm_landmarks.row(PALM_LANDMARKS_INDEX_OF_MIDDLE_FINGER_BASE);
@@ -2844,10 +2889,6 @@ protected virtual Mat preprocess(Mat image, Mat palm, out Mat rotated_palm_bbox,
28442889
// get rotation matrix
28452890
rotation_matrix = Imgproc.getRotationMatrix2D(center_palm_bbox, angle, 1.0);
28462891

2847-
// get rotated image
2848-
Mat rotated_image = new Mat();
2849-
Imgproc.warpAffine(image, rotated_image, rotation_matrix, image.size());
2850-
28512892
// get bounding boxes from rotated palm landmarks
28522893
Mat rotated_palm_landmarks = new Mat(2, 7, CvType.CV_32FC1);
28532894
Mat _a = new Mat(1, 3, CvType.CV_64FC1);
@@ -2884,7 +2925,6 @@ protected virtual Mat preprocess(Mat image, Mat palm, out Mat rotated_palm_bbox,
28842925
Point _rotated_palm_bbox_br = _rotated_palm_bbox.br();
28852926
Point wh_rotated_palm_bbox = _rotated_palm_bbox_br - _rotated_palm_bbox_tl;
28862927
Point shift_vector = new Point(PALM_BOX_SHIFT_VECTOR.x * wh_rotated_palm_bbox.x, PALM_BOX_SHIFT_VECTOR.y * wh_rotated_palm_bbox.y);
2887-
28882928
_rotated_palm_bbox_tl = _rotated_palm_bbox_tl + shift_vector;
28892929
_rotated_palm_bbox_br = _rotated_palm_bbox_br + shift_vector;
28902930

@@ -2899,51 +2939,49 @@ protected virtual Mat preprocess(Mat image, Mat palm, out Mat rotated_palm_bbox,
28992939
center_rotated_plam_bbox = new Point((_rotated_palm_bbox_tl.x + _rotated_palm_bbox_br.x) / 2, (_rotated_palm_bbox_tl.y + _rotated_palm_bbox_br.y) / 2);
29002940
wh_rotated_palm_bbox = _rotated_palm_bbox_br - _rotated_palm_bbox_tl;
29012941
Point new_half_size2 = new Point(wh_rotated_palm_bbox.x * PALM_BOX_ENLARGE_FACTOR / 2.0, wh_rotated_palm_bbox.y * PALM_BOX_ENLARGE_FACTOR / 2.0);
2902-
_rotated_palm_bbox_tl = new Point(center_rotated_plam_bbox.x - new_half_size2.x, center_rotated_plam_bbox.y - new_half_size2.x);
2903-
_rotated_palm_bbox_br = new Point(center_rotated_plam_bbox.x + new_half_size2.x, center_rotated_plam_bbox.y + new_half_size2.x);
2942+
OpenCVRect _rotated_palm_bbox_rect = new OpenCVRect((int)(center_rotated_plam_bbox.x - new_half_size2.x), (int)(center_rotated_plam_bbox.y - new_half_size2.y)
2943+
, (int)(new_half_size2.x * 2), (int)(new_half_size2.y * 2));
2944+
_rotated_palm_bbox_tl = _rotated_palm_bbox_rect.tl();
2945+
_rotated_palm_bbox_br = _rotated_palm_bbox_rect.br();
29042946
rotated_palm_bbox.put(0, 0, new double[] { _rotated_palm_bbox_tl.x, _rotated_palm_bbox_tl.y, _rotated_palm_bbox_br.x, _rotated_palm_bbox_br.y });
29052947

2906-
// Crop and resize the rotated image by the bounding box
2948+
// crop bounding box
29072949
int[] diff = new int[] {
29082950
Math.Max((int)-_rotated_palm_bbox_tl.x, 0),
29092951
Math.Max((int)-_rotated_palm_bbox_tl.y, 0),
2910-
Math.Max((int)_rotated_palm_bbox_br.x - rotated_image.width(), 0),
2911-
Math.Max((int)_rotated_palm_bbox_br.y - rotated_image.height(), 0)
2952+
Math.Max((int)_rotated_palm_bbox_br.x - tmpRotatedImage.width(), 0),
2953+
Math.Max((int)_rotated_palm_bbox_br.y - tmpRotatedImage.height(), 0)
29122954
};
29132955
Point tl = new Point(_rotated_palm_bbox_tl.x + diff[0], _rotated_palm_bbox_tl.y + diff[1]);
29142956
Point br = new Point(_rotated_palm_bbox_br.x + diff[2], _rotated_palm_bbox_br.y + diff[3]);
29152957
OpenCVRect rotated_palm_bbox_rect = new OpenCVRect(tl, br);
2916-
OpenCVRect rotated_image_rect = new OpenCVRect(0, 0, rotated_image.width(), rotated_image.height());
2917-
Mat crop = new Mat(rotated_image, rotated_image_rect.intersect(rotated_palm_bbox_rect));
2918-
2919-
//
2920-
//Core.copyMakeBorder(crop, crop, diff[1], diff[3], diff[0], diff[2], Core.BORDER_CONSTANT, Scalar.all(0));
2921-
//Mat blob = Dnn.blobFromImage(crop, 1.0 / 255.0, input_size, new Scalar(0, 0, 0), true, false, CvType.CV_32F);
2922-
//
2923-
// or
2924-
//
2925-
int tmpImageSize = (int)(Math.Max(image.width(), image.height()) * 1.5);
2926-
if (tmpImage != null && (tmpImage.width() != tmpImageSize || tmpImage.height() != tmpImageSize))
2927-
{
2928-
tmpImage.Dispose();
2929-
tmpImage = null;
2930-
}
2931-
if (tmpImage == null)
2932-
{
2933-
tmpImage = new Mat(tmpImageSize, tmpImageSize, image.type(), Scalar.all(0));
2934-
}
2935-
Mat _tmpImage_crop = new Mat(tmpImage, new OpenCVRect(0, 0, diff[0] + crop.width() + diff[2], diff[1] + crop.height() + diff[3]));
2936-
Imgproc.rectangle(_tmpImage_crop, new OpenCVRect(0, 0, _tmpImage_crop.width(), _tmpImage_crop.height()), Scalar.all(0));
2937-
Mat _tmpImage_crop2 = new Mat(tmpImage, new OpenCVRect(diff[0], diff[1], crop.width(), crop.height()));
2938-
crop.copyTo(_tmpImage_crop2);
2958+
OpenCVRect rotated_image_rect = new OpenCVRect(0, 0, tmpRotatedImage.width(), tmpRotatedImage.height());
29392959

2940-
Mat blob = Dnn.blobFromImage(_tmpImage_crop, 1.0 / 255.0, input_size, new Scalar(0, 0, 0), true, false, CvType.CV_32F);
2941-
//
2960+
// get rotated image
2961+
OpenCVRect warp_roi_rect = rotated_image_rect.intersect(rotated_palm_bbox_rect);
2962+
Mat _tmpImage_warp_roi = new Mat(tmpImage, warp_roi_rect);
2963+
Mat _tmpRotatedImage_warp_roi = new Mat(tmpRotatedImage, warp_roi_rect);
2964+
Point warp_roi_center_palm_bbox = center_palm_bbox - warp_roi_rect.tl();
2965+
Mat warp_roi_rotation_matrix = Imgproc.getRotationMatrix2D(warp_roi_center_palm_bbox, angle, 1.0);
2966+
Imgproc.warpAffine(_tmpImage_warp_roi, _tmpRotatedImage_warp_roi, warp_roi_rotation_matrix, _tmpImage_warp_roi.size());
2967+
2968+
// get rotated_palm_bbox-size rotated image
2969+
OpenCVRect crop_rect = rotated_image_rect.intersect(
2970+
new OpenCVRect(0, 0, (int)_rotated_palm_bbox_br.x - (int)_rotated_palm_bbox_tl.x, (int)_rotated_palm_bbox_br.y - (int)_rotated_palm_bbox_tl.y));
2971+
Mat _tmpImage_crop_roi = new Mat(tmpImage, crop_rect);
2972+
Imgproc.rectangle(_tmpImage_crop_roi, new OpenCVRect(0, 0, _tmpImage_crop_roi.width(), _tmpImage_crop_roi.height()), Scalar.all(0), -1);
2973+
OpenCVRect crop2_rect = rotated_image_rect.intersect(new OpenCVRect(diff[0], diff[1], _tmpRotatedImage_warp_roi.width(), _tmpRotatedImage_warp_roi.height()));
2974+
Mat _tmpImage_crop2_roi = new Mat(tmpImage, crop2_rect);
2975+
if (_tmpRotatedImage_warp_roi.size() == _tmpImage_crop2_roi.size())
2976+
_tmpRotatedImage_warp_roi.copyTo(_tmpImage_crop2_roi);
2977+
2978+
2979+
Mat blob = Dnn.blobFromImage(_tmpImage_crop_roi, 1.0 / 255.0, input_size, new Scalar(0, 0, 0), true, false, CvType.CV_32F);
29422980

29432981
// NCHW => NHWC
29442982
Core.transposeND(blob, new MatOfInt(0, 2, 3, 1), blob);
29452983

2946-
rotated_image.Dispose();
2984+
new_palm.Dispose();
29472985

29482986
return blob;
29492987
}
@@ -2954,15 +2992,16 @@ public virtual Mat infer(Mat image, Mat palm)
29542992
Mat rotated_palm_bbox;
29552993
double angle;
29562994
Mat rotation_matrix;
2957-
Mat input_blob = preprocess(image, palm, out rotated_palm_bbox, out angle, out rotation_matrix);
2995+
Mat pad_bias;
2996+
Mat input_blob = preprocess(image, palm, out rotated_palm_bbox, out angle, out rotation_matrix, out pad_bias);
29582997

29592998
// Forward
29602999
handpose_estimation_net.setInput(input_blob);
29613000
List<Mat> output_blob = new List<Mat>();
29623001
handpose_estimation_net.forward(output_blob, handpose_estimation_net.getUnconnectedOutLayersNames());
29633002

29643003
// Postprocess
2965-
Mat results = postprocess(output_blob, rotated_palm_bbox, angle, rotation_matrix);
3004+
Mat results = postprocess(output_blob, rotated_palm_bbox, angle, rotation_matrix, pad_bias);
29663005

29673006
input_blob.Dispose();
29683007
for (int i = 0; i < output_blob.Count; i++)
@@ -2973,7 +3012,7 @@ public virtual Mat infer(Mat image, Mat palm)
29733012
return results;// [bbox_coords, landmarks_coords, landmarks_coords_world, handedness, conf]
29743013
}
29753014

2976-
protected virtual Mat postprocess(List<Mat> output_blob, Mat rotated_palm_bbox, double angle, Mat rotation_matrix)
3015+
protected virtual Mat postprocess(List<Mat> output_blob, Mat rotated_palm_bbox, double angle, Mat rotation_matrix, Mat pad_bias)
29773016
{
29783017
Mat landmarks = output_blob[0];
29793018
float conf = (float)output_blob[1].get(0, 0)[0];
@@ -3050,7 +3089,10 @@ protected virtual Mat postprocess(List<Mat> output_blob, Mat rotated_palm_bbox,
30503089
center.put(0, 0, new double[] { (rotated_palm_bbox_arr[0] + rotated_palm_bbox_arr[2]) / 2.0, (rotated_palm_bbox_arr[1] + rotated_palm_bbox_arr[3]) / 2.0, 1.0 });
30513090
Mat original_center = new Mat(2, 1, CvType.CV_64FC1);
30523091
original_center.put(0, 0, new double[] { inverse_rotation_matrix.row(0).dot(center.reshape(1, 1)), inverse_rotation_matrix.row(1).dot(center.reshape(1, 1)) });
3053-
Core.add(rotated_landmarks.reshape(3, 21), new Scalar(original_center.get(0, 0)[0], original_center.get(1, 0)[0], 0.0), landmarks.reshape(3, 21));
3092+
3093+
Core.add(rotated_landmarks.reshape(3, 21)
3094+
, new Scalar(original_center.get(0, 0)[0] + pad_bias.get(0, 0)[0], original_center.get(1, 0)[0] + pad_bias.get(1, 0)[0], 0.0)
3095+
, landmarks.reshape(3, 21));
30543096

30553097
// get bounding box from rotated_landmarks
30563098
Point[] landmarks_points = new Point[21];
@@ -3220,6 +3262,9 @@ public virtual void dispose()
32203262

32213263
if (tmpImage != null)
32223264
tmpImage.Dispose();
3265+
3266+
if (tmpRotatedImage != null)
3267+
tmpRotatedImage.Dispose();
32233268
}
32243269
}
32253270
}

Assets/OpenCVForUnity/Examples/MainModules/dnn/HumanSegmentationExample/HumanSegmentationExample.cs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@ namespace OpenCVForUnityExample
2424
[RequireComponent(typeof(WebCamTextureToMatHelper))]
2525
public class HumanSegmentationExample : MonoBehaviour
2626
{
27+
/// <summary>
28+
/// The compose bg image toggle.
29+
/// </summary>
30+
public Toggle composeBGImageToggle;
31+
32+
/// <summary>
33+
/// The hide person toggle.
34+
/// </summary>
35+
public Toggle hidePersonToggle;
36+
37+
/// <summary>
38+
/// The background image texture.
39+
/// </summary>
40+
public Texture2D backGroundImageTexture;
41+
2742
/// <summary>
2843
/// The texture.
2944
/// </summary>
@@ -44,6 +59,16 @@ public class HumanSegmentationExample : MonoBehaviour
4459
/// </summary>
4560
Mat maskMat;
4661

62+
/// <summary>
63+
/// The background mask mat.
64+
/// </summary>
65+
Mat bgMaskMat;
66+
67+
/// <summary>
68+
/// The background image mat.
69+
/// </summary>
70+
Mat backGroundImageMat;
71+
4772
/// <summary>
4873
/// The net.
4974
/// </summary>
@@ -163,6 +188,16 @@ public void OnWebCamTextureToMatHelperInitialized()
163188
rgbMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC3);
164189
maskMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC1);
165190

191+
bgMaskMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC1);
192+
backGroundImageMat = new Mat(webCamTextureMat.size(), CvType.CV_8UC4, new Scalar(39, 255, 86, 255));
193+
if (backGroundImageTexture != null)
194+
{
195+
using (Mat bgMat = new Mat(backGroundImageTexture.height, backGroundImageTexture.width, CvType.CV_8UC4))
196+
{
197+
Utils.texture2DToMat(backGroundImageTexture, bgMat);
198+
Imgproc.resize(bgMat, backGroundImageMat, backGroundImageMat.size());
199+
}
200+
}
166201
}
167202

168203
/// <summary>
@@ -178,6 +213,12 @@ public void OnWebCamTextureToMatHelperDisposed()
178213
if (maskMat != null)
179214
maskMat.Dispose();
180215

216+
if (bgMaskMat != null)
217+
bgMaskMat.Dispose();
218+
219+
if (backGroundImageMat != null)
220+
backGroundImageMat.Dispose();
221+
181222
if (texture != null)
182223
{
183224
Texture2D.Destroy(texture);
@@ -225,14 +266,23 @@ void Update()
225266
Mat result = new Mat();
226267
Core.reduceArgMax(prob, result, 1);
227268
//result.reshape(0, new int[] { 192,192});
228-
result.convertTo(result, CvType.CV_8U);
269+
result.convertTo(result, CvType.CV_8U, 255.0);
229270
//Debug.Log("result.ToString(): " + result.ToString());
230271

231-
232272
Mat mask192x192 = new Mat(192, 192, CvType.CV_8UC1, (IntPtr)result.dataAddr());
233273
Imgproc.resize(mask192x192, maskMat, rgbaMat.size(), Imgproc.INTER_NEAREST);
234274

235-
rgbaMat.setTo(new Scalar(255, 255, 255,255), maskMat);
275+
if (composeBGImageToggle.isOn)
276+
{
277+
// Compose the background image.
278+
Core.bitwise_not(maskMat, bgMaskMat);
279+
backGroundImageMat.copyTo(rgbaMat, bgMaskMat);
280+
}
281+
282+
if (hidePersonToggle.isOn)
283+
{
284+
rgbaMat.setTo(new Scalar(255, 255, 255, 255), maskMat);
285+
}
236286

237287
mask192x192.Dispose();
238288
result.Dispose();
@@ -306,7 +356,6 @@ public void OnChangeCameraButtonClick()
306356
{
307357
webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.requestedIsFrontFacing;
308358
}
309-
310359
}
311360
}
312361
#endif

0 commit comments

Comments
 (0)