Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/FaceRecognitionDotNet/FaceRecognition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ public static IEnumerable<double> FaceDistances(IEnumerable<FaceEncoding> faceEn
/// <param name="model">The model of face detector to detect in image. If <paramref name="knownFaceLocation"/> is not null, this value is ignored.</param>
/// <returns>An enumerable collection of face feature data corresponds to all faces in specified image.</returns>
/// <exception cref="ArgumentNullException"><paramref name="image"/> is null.</exception>
/// <exception cref="InvalidOperationException"><paramref name="knownFaceLocation"/> contains no elements.</exception>
/// <exception cref="ObjectDisposedException"><paramref name="image"/> or this object or custom face landmark detector is disposed.</exception>
/// <exception cref="NotSupportedException"><see cref="PredictorModel.Custom"/> is not supported.</exception>
public IEnumerable<FaceEncoding> FaceEncodings(Image image,
Expand All @@ -382,6 +383,9 @@ public IEnumerable<FaceEncoding> FaceEncodings(Image image,
if (predictorModel == PredictorModel.Custom)
throw new NotSupportedException("FaceRecognitionDotNet.PredictorModel.Custom is not supported.");

if (knownFaceLocation != null && !knownFaceLocation.Any())
throw new InvalidOperationException($"{nameof(knownFaceLocation)} contains no elements.");

image.ThrowIfDisposed();
this.ThrowIfDisposed();

Expand All @@ -403,6 +407,7 @@ public IEnumerable<FaceEncoding> FaceEncodings(Image image,
/// <param name="model">The model of face detector to detect in image. If <paramref name="faceLocations"/> is not null, this value is ignored.</param>
/// <returns>An enumerable collection of dictionary of face parts locations (eyes, nose, etc).</returns>
/// <exception cref="ArgumentNullException"><paramref name="faceImage"/> is null.</exception>
/// <exception cref="InvalidOperationException"><paramref name="faceLocations"/> contains no elements.</exception>
/// <exception cref="ObjectDisposedException"><paramref name="faceImage"/> or this object or custom face landmark detector is disposed.</exception>
/// <exception cref="NotSupportedException">The custom face landmark detector is not ready.</exception>
public IEnumerable<IDictionary<FacePart, IEnumerable<FacePoint>>> FaceLandmark(Image faceImage,
Expand All @@ -413,6 +418,9 @@ public IEnumerable<IDictionary<FacePart, IEnumerable<FacePoint>>> FaceLandmark(I
if (faceImage == null)
throw new ArgumentNullException(nameof(faceImage));

if (faceLocations != null && !faceLocations.Any())
throw new InvalidOperationException($"{nameof(faceLocations)} contains no elements.");

faceImage.ThrowIfDisposed();
this.ThrowIfDisposed();

Expand Down
2 changes: 2 additions & 0 deletions src/FaceRecognitionDotNet/docs/FaceRecognitionDotNet.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/FaceRecognitionDotNet/docs/ja/FaceRecognitionDotNet.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 65 additions & 2 deletions test/FaceRecognitionDotNet.Tests/FaceRecognitionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,27 @@ public void FaceEncodingsException()
catch (ArgumentNullException)
{
}

try
{
var path = Path.Combine(ImageDirectory, TwoPersonFile);
if (!File.Exists(path))
{
var binary = new HttpClient().GetByteArrayAsync($"{TwoPersonUrl}/{TwoPersonFile}").Result;

Directory.CreateDirectory(ImageDirectory);
File.WriteAllBytes(path, binary);
}

using (var image = FaceRecognition.LoadImageFile(path))
{
var _ = this._FaceRecognition.FaceEncodings(image, new Location[0]).ToArray();
Assert.True(false, $"{nameof(FaceRecognition.FaceEncodings)} must throw {typeof(InvalidOperationException)}.");
}
}
catch (InvalidOperationException)
{
}
}

[Fact]
Expand Down Expand Up @@ -533,6 +554,48 @@ public void FaceLandmarkException()
catch (ArgumentNullException)
{
}

try
{
var path = Path.Combine(ImageDirectory, TwoPersonFile);
if (!File.Exists(path))
{
var binary = new HttpClient().GetByteArrayAsync($"{TwoPersonUrl}/{TwoPersonFile}").Result;

Directory.CreateDirectory(ImageDirectory);
File.WriteAllBytes(path, binary);
}

using (var image = FaceRecognition.LoadImageFile(path))
{
var _ = this._FaceRecognition.FaceLandmark(image, new Location[0]).ToArray();
Assert.True(false, $"{nameof(FaceRecognition.FaceLandmark)} must throw {typeof(InvalidOperationException)}.");
}
}
catch (InvalidOperationException)
{
}
}

[Fact]
public void FaceLandmarkEmpty()
{
var path = Path.Combine(ImageDirectory, TwoPersonFile);
if (!File.Exists(path))
{
var binary = new HttpClient().GetByteArrayAsync($"{TwoPersonUrl}/{TwoPersonFile}").Result;

Directory.CreateDirectory(ImageDirectory);
File.WriteAllBytes(path, binary);
}

// empty image should return empty result
using(var bitmap = new Bitmap(640, 480, PixelFormat.Format24bppRgb))
using (var image = FaceRecognition.LoadImage(bitmap))
{
var landmarks = this._FaceRecognition.FaceLandmark(image).ToArray();
Assert.True(!landmarks.Any(), $"{nameof(FaceRecognition.FaceLandmark)} should return empty elements.");
}
}

[Fact]
Expand Down Expand Up @@ -2065,10 +2128,10 @@ private void FaceLocation(string testName, int numberOfTimesToUpsample, Model mo
}
}

private IEnumerable<FullObjectDetection> RawFaceLandmarks(Image img, IEnumerable<Location> faceLocations = null, PredictorModel model = PredictorModel.Large)
private IEnumerable<FullObjectDetection> RawFaceLandmarks(Image img, IEnumerable<Location> faceLocations = null, PredictorModel predictorModel = PredictorModel.Large)
{
var method = this._FaceRecognition.GetType().GetMethod("RawFaceLandmarks", BindingFlags.Instance | BindingFlags.NonPublic);
return method.Invoke(this._FaceRecognition, new object[] { img, faceLocations, model }) as IEnumerable<FullObjectDetection>;
return method.Invoke(this._FaceRecognition, new object[] { img, faceLocations, predictorModel, Model.Hog }) as IEnumerable<FullObjectDetection>;
}

private IEnumerable<MModRect> RawFaceLocations(Image img, int numberOfTimesToUpsample = 1, Model model = Model.Hog)
Expand Down