diff options
Diffstat (limited to 'src/Tizen.Multimedia.Vision/MediaVision')
50 files changed, 5726 insertions, 0 deletions
diff --git a/src/Tizen.Multimedia.Vision/MediaVision/Barcode.cs b/src/Tizen.Multimedia.Vision/MediaVision/Barcode.cs new file mode 100755 index 0000000..6a44d7d --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/Barcode.cs @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a detected barcode. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class Barcode + { + /// <summary> + /// Initializes a new instance of the <see cref="Barcode"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Barcode(Quadrangle region, string message, BarcodeType type) + { + Region = region; + Message = message; + Type = type; + } + + /// <summary> + /// The quadrangle location of detected barcode. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Quadrangle Region { get; } + + /// <summary> + /// The decoded message of barcode. + /// </summary> + /// <since_tizen> 3</since_tizen> + public string Message { get; } + + /// <summary> + /// The type of detected barcode. + /// </summary> + /// <since_tizen> 3</since_tizen> + public BarcodeType Type { get; } + + public override string ToString() => + $"Region={Region}, Message={Message}, Type={Type.ToString()}"; + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionConfiguration.cs new file mode 100755 index 0000000..1da6986 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionConfiguration.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="BarcodeDetector"/>. + /// </summary> + /// <seealso cref="BarcodeDetector"/> + /// <since_tizen> 3</since_tizen> + public class BarcodeDetectionConfiguration : EngineConfiguration + { + private const string KeyAttrTarget = "MV_BARCODE_DETECT_ATTR_TARGET"; + + /// <summary> + /// Initializes a new instance of the <see cref="BarcodeDetectionConfiguration"/> class. + /// </summary> + /// <exception cref="System.NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public BarcodeDetectionConfiguration() : base("barcode_detection") + { + } + + /// <summary> + /// Gets or sets the target of the barcode detection. + /// </summary> + /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception> + /// <exception cref="System.ObjectDisposedException">The <see cref="BarcodeDetectionConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public BarcodeDetectionTarget Target + { + get + { + return (BarcodeDetectionTarget)GetInt(KeyAttrTarget); + } + set + { + ValidationUtil.ValidateEnum(typeof(BarcodeDetectionTarget), value); + Set(KeyAttrTarget, (int)value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionTarget.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionTarget.cs new file mode 100755 index 0000000..231dce5 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetectionTarget.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the target of <see cref="BarcodeDetector"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum BarcodeDetectionTarget + { + /// <summary> + /// 1D and 2D. + /// </summary> + /// <since_tizen> 3</since_tizen> + All, + + /// <summary> + /// 1D barcode only. + /// </summary> + /// <since_tizen> 3</since_tizen> + Barcode1D, + + /// <summary> + /// 2D barcode only. + /// </summary> + /// <since_tizen> 3</since_tizen> + Barcode2D, + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetector.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetector.cs new file mode 100755 index 0000000..df4d6da --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeDetector.cs @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using InteropBarcode = Interop.MediaVision.BarcodeDetector; +using Unmanaged = Interop.MediaVision; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to detect barcodes on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class BarcodeDetector + { + /// <summary> + /// Detects barcodes on source and reads message from it. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> instance.</param> + /// <param name="roi">Region of interest - rectangular area on the source which will be used for + /// barcode detection. Note that roi should be inside area on the source.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> already has been disposed of.</exception> + /// <returns>A task that represents the asynchronous detect operation.</returns> + /// <seealso cref="Barcode"/> + /// <since_tizen> 3</since_tizen> + public static async Task<IEnumerable<Barcode>> DetectAsync(MediaVisionSource source, + Rectangle roi) + { + return await DetectAsync(source, roi, null); + } + + /// <summary> + /// Detects barcodes on source and reads message from it with <see cref="BarcodeDetectionConfiguration"/>. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> instance.</param> + /// <param name="roi">Region of interest - rectangular area on the source which will be used for + /// barcode detection. Note that roi should be inside area on the source.</param> + /// <param name="config">The configuration of the barcode detector. This value can be null.</param> + /// <returns>A task that represents the asynchronous detect operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> already has been disposed of.\n + /// -or-\n + /// <paramref name="config"/> already has been disposed of. + /// </exception> + /// <seealso cref="Barcode"/> + /// <since_tizen> 3</since_tizen> + public static async Task<IEnumerable<Barcode>> DetectAsync(MediaVisionSource source, + Rectangle roi, BarcodeDetectionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + var tcs = new TaskCompletionSource<IEnumerable<Barcode>>(); + + using (var cb = ObjectKeeper.Get(GetCallback(tcs))) + { + InteropBarcode.Detect(source.Handle, EngineConfiguration.GetHandle(config), + roi.ToMarshalable(), cb.Target).Validate("Failed to detect barcode."); + + return await tcs.Task; + } + } + + private static Barcode[] CreateBarcodes(Unmanaged.Quadrangle[] locations, string[] messages, + BarcodeType[] types, int numberOfBarcodes) + { + Barcode[] barcodes = new Barcode[numberOfBarcodes]; + + for (int i = 0; i < numberOfBarcodes; i++) + { + barcodes[i] = new Barcode(locations[i].ToApiStruct(), messages[i], types[i]); + + Log.Info(MediaVisionLog.Tag, barcodes[i].ToString()); + } + + return barcodes; + } + + private static InteropBarcode.DetectedCallback GetCallback(TaskCompletionSource<IEnumerable<Barcode>> tcs) + { + return (IntPtr mvSource, IntPtr engineCfg, Unmanaged.Quadrangle[] locations, string[] messages, + BarcodeType[] types, int numberOfBarcodes, IntPtr userData) => + { + Log.Info(MediaVisionLog.Tag, $"Barcodes detected, count : {numberOfBarcodes}"); + + try + { + tcs.TrySetResult(CreateBarcodes(locations, messages, types, numberOfBarcodes)); + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle barcode detection callback", e); + tcs.TrySetException(e); + } + }; + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerationConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerationConfiguration.cs new file mode 100755 index 0000000..eb29a04 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerationConfiguration.cs @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using Tizen.Common; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="BarcodeGenerator"/> instances. + /// </summary> + /// <seealso cref="BarcodeGenerator"/> + /// <since_tizen> 3</since_tizen> + public class BarcodeGenerationConfiguration : EngineConfiguration + { + private const string KeyTextAttr = "MV_BARCODE_GENERATE_ATTR_TEXT"; + private const string KeyForegroundColorAttr = "MV_BARCODE_GENERATE_ATTR_COLOR_FRONT"; + private const string KeyBackgroundColorAttr = "MV_BARCODE_GENERATE_ATTR_COLOR_BACK"; + + /// <summary> + /// Initializes a new instance of the <see cref="BarcodeGenerationConfiguration"/> class. + /// </summary> + /// <exception cref="System.NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public BarcodeGenerationConfiguration() : base("barcode_generation") + { + } + + /// <summary> + /// Gets or sets the text visibility of the barcode to be generated. + /// </summary> + /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public Visibility TextVisibility + { + get + { + return (Visibility)GetInt(KeyTextAttr); + } + set + { + ValidationUtil.ValidateEnum(typeof(Visibility), value); + Set(KeyTextAttr, (int)value); + } + } + + private Color _foregroundColor = Color.Black; + + /// <summary> + /// Gets or sets the foreground color of the barcode to be generated. + /// </summary> + /// <remarks> + /// The alpha value of the color will be ignored. + /// </remarks> + /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public Color ForegroundColor + { + get + { + return _foregroundColor; + } + set + { + Set(KeyForegroundColorAttr, string.Format("{0:x2}{1:x2}{2:x2}", value.R, value.G, value.B)); + _foregroundColor = value; + } + } + + private Color _backgroundColor = Color.White; + + /// <summary> + /// Gets or sets the background color of the barcode to be generated. + /// </summary> + /// <remarks> + /// The alpha value of the color will be ignored. + /// </remarks> + /// <exception cref="ObjectDisposedException">The <see cref="BarcodeGenerationConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public Color BackgroundColor + { + get + { + return _backgroundColor; + } + set + { + Set(KeyBackgroundColorAttr, string.Format("{0:x2}{1:x2}{2:x2}", value.R, value.G, value.B)); + _backgroundColor = value; + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerator.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerator.cs new file mode 100755 index 0000000..2d4269d --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeGenerator.cs @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using InteropBarcode = Interop.MediaVision.BarcodeGenerator; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to generate barcodes and QR codes. + /// Different encoding types <see cref="QrMode"/> , error correction codes <see cref="ErrorCorrectionLevel"/> + /// and code versions are supported for QRCodes. + /// </summary> + /// <seealso cref="BarcodeGenerationConfiguration"/> + /// <since_tizen> 3</since_tizen> + public static class BarcodeGenerator + { + private const int NoneErrorCorrection = (int)ErrorCorrectionLevel.High + 1; + private const int NoneQrMode = (int)QrMode.Utf8 + 1; + + private static MediaVisionSource GenerateSource(BarcodeGenerationConfiguration config, + string message, BarcodeType type, int qrMode, int qrEcc, int qrVersion) + { + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } + + ValidationUtil.ValidateEnum(typeof(BarcodeType), type); + + MediaVisionSource source = new MediaVisionSource(); + try + { + InteropBarcode.GenerateSource(EngineConfiguration.GetHandle(config), + message, type, qrMode, qrEcc, qrVersion, source.Handle). + Validate("Failed to generate source"); + } + catch (Exception) + { + source.Dispose(); + throw; + } + return source; + } + + /// <summary> + /// Generates a QR image with the specified message. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param> + /// <returns><see cref="MediaVisionSource"/> containing the generated QR image.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="qrConfig"/> is null.\n + /// -or-\n + /// <paramref name="message"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <seealso cref="QrMode"/> + /// <since_tizen> 3</since_tizen> + public static MediaVisionSource GenerateSource(string message, QrConfiguration qrConfig) + { + return GenerateSource(message, qrConfig, null); + } + + /// <summary> + /// Generates a QR image with the specified message with <see cref="BarcodeGenerationConfiguration"/>. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param> + /// <param name="config">The configuration of the barcode generator. This value can be null.</param> + /// <returns><see cref="MediaVisionSource"/> containing the generated QR image.</returns> + /// <remarks> + /// <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>, + /// because the text visibility is not supported in the QR code. + /// </remarks> + /// <exception cref="ArgumentNullException"> + /// <paramref name="qrConfig"/> is null.\n + /// -or-\n + /// <paramref name="message"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>. + /// </exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <see cref="BarcodeGenerationConfiguration.TextVisibility"/> is the <see cref="Visibility.Visible"/>. + /// </exception> + /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception> + /// <seealso cref="QrMode"/> + /// <since_tizen> 3</since_tizen> + public static MediaVisionSource GenerateSource(string message, QrConfiguration qrConfig, + BarcodeGenerationConfiguration config) + { + if (qrConfig == null) + { + throw new ArgumentNullException(nameof(qrConfig)); + } + + if (config != null) + { + if (config.TextVisibility == Visibility.Visible) + { + throw new NotSupportedException("Text can't be visible in QR."); + } + } + + return GenerateSource(config, message, BarcodeType.QR, (int)qrConfig.Mode, + (int)qrConfig.ErrorCorrectionLevel, qrConfig.Version); + } + + /// <summary> + /// Generates a barcode image with the specified message. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="type">Type of the barcode to be generated.</param> + /// <returns><see cref="MediaVisionSource"/> containing the generated barcode image.</returns> + /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="type"/> is <see cref="BarcodeType.QR"/>.\n + /// -or-\n + /// <paramref name="type"/> is invalid. + /// -or-\n + /// <paramref name="message"/> contains illegal characters. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static MediaVisionSource GenerateSource(string message, BarcodeType type) + { + return GenerateSource(message, type, null); + } + + /// <summary> + /// Generates a barcode image with the specified message and <see cref="BarcodeGenerationConfiguration"/>. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="type">Type of the barcode to be generated.</param> + /// <param name="config">The configuration of the barcode generator. This value can be null.</param> + /// <returns><see cref="MediaVisionSource"/> containing the generated barcode image.</returns> + /// <exception cref="ArgumentNullException"><paramref name="message"/> is null.</exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="type"/> is <see cref="BarcodeType.QR"/>. + /// -or-\n + /// <paramref name="type"/> is invalid. + /// -or-\n + /// <paramref name="message"/> contains illegal characters. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public static MediaVisionSource GenerateSource(string message, BarcodeType type, + BarcodeGenerationConfiguration config) + { + if (type == BarcodeType.QR) + { + throw new ArgumentException($"Invalid barcode type : {type}."); + } + + return GenerateSource(config, message, type, NoneQrMode, NoneErrorCorrection, 0); + } + + private static void GenerateImage(BarcodeGenerationConfiguration config, + string message, BarcodeType type, BarcodeImageConfiguration imageConfig, + int qrMode, int qrEcc, int qrVersion) + { + if (message == null) + { + throw new ArgumentNullException(nameof(message)); + } + + if (imageConfig == null) + { + throw new ArgumentNullException(nameof(imageConfig)); + } + + ValidationUtil.ValidateEnum(typeof(BarcodeType), type); + + InteropBarcode.GenerateImage(EngineConfiguration.GetHandle(config), message, + imageConfig.Width, imageConfig.Height, type, qrMode, qrEcc, qrVersion, + imageConfig.Path, imageConfig.Format). + Validate("Failed to generate image"); + } + + /// <summary> + /// Generates a QR image file with the specified message. + /// </summary> + /// <remarks> + /// <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>, + /// because the text visibility is not supported in the QR code. + /// </remarks> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param> + /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains information about the file to be generated.</param> + /// <exception cref="ArgumentNullException"> + /// <paramref name="messsage"/> is null.\n + /// -or-\n + /// <paramref name="qrConfig"/> is null.\n + /// -or-\n + /// <paramref name="imageConfig"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <seealso cref="QrMode"/> + /// <since_tizen> 3</since_tizen> + public static void GenerateImage(string message, QrConfiguration qrConfig, + BarcodeImageConfiguration imageConfig) + { + GenerateImage(message, qrConfig, imageConfig, null); + } + + /// <summary> + /// Generates a QR image file with the specified message and <see cref="BarcodeGenerationConfiguration"/>. + /// </summary> + /// <remarks> + /// <see cref="BarcodeGenerationConfiguration.TextVisibility"/> must be <see cref="Visibility.Invisible"/>, + /// because the text visibility is not supported in the QR code. + /// </remarks> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="qrConfig">The <see cref="QrConfiguration"/> instance.</param> + /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains + /// information about the file to be generated.</param> + /// <param name="config">The configuration of the barcode generator. This value can be null.</param> + /// <exception cref="ArgumentNullException"> + /// <paramref name="messsage"/> is null.\n + /// -or-\n + /// <paramref name="qrConfig"/> is null.\n + /// -or-\n + /// <paramref name="imageConfig"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="message"/> contains characters which are illegal by the <see cref="QrMode"/>. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <see cref="BarcodeGenerationConfiguration.TextVisibility"/> is the <see cref="Visibility.Visible"/>. + /// </exception> + /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public static void GenerateImage(string message, QrConfiguration qrConfig, + BarcodeImageConfiguration imageConfig, BarcodeGenerationConfiguration config) + { + if (qrConfig == null) + { + throw new ArgumentNullException(nameof(qrConfig)); + } + + if (config != null) + { + if (config.TextVisibility == Visibility.Visible) + { + throw new NotSupportedException("Text can't be visible in QR."); + } + } + + GenerateImage(config, message, BarcodeType.QR, imageConfig, (int)qrConfig.Mode, + (int)qrConfig.ErrorCorrectionLevel, qrConfig.Version); + } + + /// <summary> + /// Generates a barcode image file with the specified message. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="type">Type of the barcode to be generated.</param> + /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains + /// information about the file to be generated.</param> + /// <exception cref="ArgumentNullException"> + /// <paramref name="messsage"/> is null.\n + /// -or-\n + /// <paramref name="imageConfig"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="type"/> is <see cref="BarcodeType.QR"/>. + /// -or-\n + /// <paramref name="type"/> is invalid. + /// -or-\n + /// <paramref name="message"/> contains illegal characters. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static void GenerateImage(string message, BarcodeType type, BarcodeImageConfiguration imageConfig) + { + GenerateImage(message, type, imageConfig, null); + } + + /// <summary> + /// Generates a barcode image file with the specified message and <see cref="BarcodeGenerationConfiguration"/>. + /// </summary> + /// <param name="message">The message to be encoded in the barcode.</param> + /// <param name="type">Type of the barcode to be generated.</param> + /// <param name="imageConfig">The <see cref="BarcodeImageConfiguration"/> that contains + /// information about the file to be generated.</param> + /// <param name="config">The configuration of the barcode generator. This value can be null.</param> + /// <exception cref="ArgumentNullException"> + /// <paramref name="messsage"/> is null.\n + /// -or-\n + /// <paramref name="imageConfig"/> is null. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="message"/> is too long.\n + /// -or-\n + /// <paramref name="type"/> is <see cref="BarcodeType.QR"/>. + /// -or-\n + /// <paramref name="type"/> is invalid. + /// -or-\n + /// <paramref name="message"/> contains illegal characters. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to write a file.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="config"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public static void GenerateImage(string message, + BarcodeType type, BarcodeImageConfiguration imageConfig, BarcodeGenerationConfiguration config) + { + if (type == BarcodeType.QR) + { + throw new ArgumentException($"Invalid barcode type : {type}."); + } + GenerateImage(config, message, type, imageConfig, NoneQrMode, NoneErrorCorrection, 0); + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageConfiguration.cs new file mode 100755 index 0000000..6227c88 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageConfiguration.cs @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration for the image to be generated by <see cref="BarcodeGenerator"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class BarcodeImageConfiguration + { + /// <summary> + /// Initializes a new instance of the <see cref="BarcodeImageConfiguration"/> class. + /// </summary> + /// <remarks> + /// The mediastorage privilege(http://tizen.org/privilege/mediastorage) is needed if image path is relevant to media storage.\n + /// The externalstorage privilege(http://tizen.org/privilege/externalstorage) is needed if image path is relevant to external storage. + /// </remarks> + /// <param name="size">The <see cref="Size"/> of the generated image.</param> + /// <param name="path">The path to the file to be generated.</param> + /// <param name="imageFormat">The format of the output image.</param> + /// <exception cref="ArgumentOutOfRangeException"> + /// The width of <paramref name="size"/> is less than or equal to zero.\n + /// -or-\n + /// The height of <paramref name="size"/> is less than or equal to zero. + /// </exception> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="ArgumentException"><paramref name="imageFormat"/> is invalid.</exception> + /// <code> + /// BarcodeImageConfiguration imageConfig = new BarcodeImageConfiguration(new Size(500, 400), "/opt/usr/test-barcode-generate-new", BarcodeImageFormat.JPG); + /// </code> + /// <since_tizen> 3</since_tizen> + public BarcodeImageConfiguration(Size size, string path, BarcodeImageFormat imageFormat) + { + if (size.Width <= 0) + { + throw new ArgumentOutOfRangeException(nameof(Size.Width), size.Width, + "width can't be less than or equal to zero."); + } + + if (size.Height <= 0) + { + throw new ArgumentOutOfRangeException(nameof(Size.Height), size.Height, + "height can't be less than or equal to zero."); + } + + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + ValidationUtil.ValidateEnum(typeof(BarcodeImageFormat), imageFormat); + + Size = size; + Path = path; + Format = imageFormat; + } + + /// <summary> + /// Initializes a new instance of the <see cref="BarcodeImageConfiguration"/> class. + /// </summary> + /// <remarks> + /// The mediastorage privilege(http://tizen.org/privilege/mediastorage) is needed if image path is relevant to media storage.\n + /// The externalstorage privilege(http://tizen.org/privilege/externalstorage) is needed if image path is relevant to external storage. + /// </remarks> + /// <param name="width">The width of the image to be generated.</param> + /// <param name="height">The height of the image to be generated.</param> + /// <param name="path">The path to the file to be generated.</param> + /// <param name="imageFormat">The format of the output image.</param> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="width"/> is less than or equal to zero.\n + /// -or-\n + /// <paramref name="height"/> is less than or equal to zero. + /// </exception> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="ArgumentException"><paramref name="imageFormat"/> is invalid.</exception> + /// <code> + /// BarcodeImageConfiguration imageConfig = new BarcodeImageConfiguration(500, 400, "/opt/usr/test-barcode-generate-new", BarcodeImageFormat.JPG); + /// </code> + /// <since_tizen> 3</since_tizen> + public BarcodeImageConfiguration(int width, int height, string path, BarcodeImageFormat imageFormat) + : this(new Size(width, height), path, imageFormat) + { + } + + /// <summary> + /// Gets the size of the image. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Size Size { get; } + + /// <summary> + /// Gets the width of the image. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int Width => Size.Width; + + /// <summary> + /// Gets the height of the image. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int Height => Size.Height; + + /// <summary> + /// Gets the path to the file that has to be generated. + /// </summary> + /// <remarks> + /// The mediastorage privilege http://tizen.org/privilege/mediastorage is needed if image path is relevant to media storage.\n + /// The externalstorage privilege http://tizen.org/privilege/externalstorage is needed if image path is relevant to external storage. + /// </remarks> + /// <since_tizen> 3</since_tizen> + public string Path { get; } + + /// <summary> + /// Gets the format of the output image. + /// </summary> + /// <since_tizen> 3</since_tizen> + public BarcodeImageFormat Format { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageFormat.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageFormat.cs new file mode 100755 index 0000000..5481510 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeImageFormat.cs @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies supported image formats for <see cref="BarcodeGenerator"/> + /// </summary> + /// <seealso cref="BarcodeImageConfiguration"/> + /// <since_tizen> 3</since_tizen> + public enum BarcodeImageFormat + { + /// <summary> + /// BMP image format. + /// </summary> + /// <since_tizen> 3</since_tizen> + Bmp, + /// <summary> + /// JPEG image format. + /// </summary> + /// <since_tizen> 3</since_tizen> + Jpeg, + /// <summary> + /// PNG image format. + /// </summary> + /// <since_tizen> 3</since_tizen> + Png + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/BarcodeType.cs b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeType.cs new file mode 100755 index 0000000..2cc4283 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/BarcodeType.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the supported barcode types. + /// </summary> + /// <remarks> + /// QR codes (versions 1 to 40) and set of 1D barcodes are supported + /// </remarks> + /// <seealso cref="BarcodeDetector"/> + /// <seealso cref="BarcodeGenerator"/> + /// <since_tizen> 3</since_tizen> + public enum BarcodeType + { + /// <summary> + /// 2D barcode - Quick Response code. + /// </summary> + /// <since_tizen> 3</since_tizen> + QR, + /// <summary> + /// 1D barcode - Universal Product Code with 12-digit. + /// </summary> + /// <since_tizen> 3</since_tizen> + UpcA, + /// <summary> + /// 1D barcode - Universal Product Code with 6-digit. + /// </summary> + /// <since_tizen> 3</since_tizen> + UpcE, + /// <summary> + /// 1D barcode - International Article Number with 8-digit. + /// </summary> + /// <since_tizen> 3</since_tizen> + Ean8, + /// <summary> + /// 1D barcode - International Article Number with 13-digit. + /// </summary> + /// <since_tizen> 3</since_tizen> + Ean13, + /// <summary> + /// 1D barcode - Code 128. + /// </summary> + /// <since_tizen> 3</since_tizen> + Code128, + /// <summary> + /// 1D barcode - Code 39. + /// </summary> + /// <since_tizen> 3</since_tizen> + Code39, + /// <summary> + /// 1D barcode - Interleaved Two of Five. + /// </summary> + /// <since_tizen> 3</since_tizen> + I25 + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/Colorspace.cs b/src/Tizen.Multimedia.Vision/MediaVision/Colorspace.cs new file mode 100755 index 0000000..79135e0 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/Colorspace.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies colorspaces for MediaVision. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum Colorspace + { + /// <summary> + /// The colorspace type is invalid. + /// </summary> + /// <since_tizen> 3</since_tizen> + Invalid, + /// <summary> + /// The colorspace type is Y800. + /// </summary> + /// <since_tizen> 3</since_tizen> + Y800, + /// <summary> + /// The colorspace type is I420. + /// </summary> + /// <since_tizen> 3</since_tizen> + I420, + /// <summary> + /// The colorspace type is NV12. + /// </summary> + /// <since_tizen> 3</since_tizen> + NV12, + /// <summary> + /// The colorspace type is YV12. + /// </summary> + /// <since_tizen> 3</since_tizen> + YV12, + /// <summary> + /// The colorspace type is NV21. + /// </summary> + /// <since_tizen> 3</since_tizen> + NV21, + /// <summary> + /// The colorspace type is YUYV. + /// </summary> + /// <since_tizen> 3</since_tizen> + Yuyv, + /// <summary> + /// The colorspace type is UYVY. + /// </summary> + /// <since_tizen> 3</since_tizen> + Uyvy, + /// <summary> + /// The colorspace type is 422P. + /// </summary> + /// <since_tizen> 3</since_tizen> + Yuv422P, + /// <summary> + /// The colorspace type is RGB565. + /// </summary> + /// <since_tizen> 3</since_tizen> + Rgb565, + /// <summary> + /// The colorspace type is RGB888. + /// </summary> + /// <since_tizen> 3</since_tizen> + Rgb888, + /// <summary> + /// The colorspace type is RGBA. + /// </summary> + /// <since_tizen> 3</since_tizen> + Rgba + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/EngineConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/EngineConfiguration.cs new file mode 100755 index 0000000..7d59ccf --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/EngineConfiguration.cs @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using Tizen.System; +using System.Runtime.InteropServices; +using static Interop.MediaVision; + +namespace Tizen.Multimedia +{ + /// <summary> + /// A base class for configuration classes. + /// </summary> + /// <since_tizen> 3</since_tizen> + public abstract class EngineConfiguration : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + private const string _featurePath = "http://tizen.org/feature/vision."; + + private bool IsSupportedEngineType(string type) + { + bool isSupported = false; + + string featureType = _featurePath + type; + + bool ret = SystemInfo.TryGetValue(featureType, out isSupported); + + return (isSupported && ret) ? true : false; + } + + private bool IsSupportedEngineType(string type1, string type2) + { + return (IsSupportedEngineType(type1) && IsSupportedEngineType(type2)) ? true : false; + } + + internal EngineConfiguration(string engineType) + { + if (IsSupportedEngineType(engineType) == false) + { + throw new NotSupportedException($"{engineType} : Not Supported"); + } + + EngineConfig.Create(out _handle).Validate("Failed to create media vision engine."); + } + + internal EngineConfiguration(string engineType1, string engineType2) + { + + if (IsSupportedEngineType(engineType1, engineType2) == false) + { + throw new NotSupportedException($"{engineType1} or {engineType2} : Not Supported"); + } + + EngineConfig.Create(out _handle).Validate("Failed to create media vision engine."); + } + + ~EngineConfiguration() + { + Dispose(false); + } + + internal static IntPtr GetHandle(EngineConfiguration config) + { + if (config == null) + { + return IntPtr.Zero; + } + + if (config._disposed) + { + throw new ObjectDisposedException(config.GetType().Name); + } + + return config._handle; + } + + internal void Set(string key, double value) + { + EngineConfig.SetDouble(Handle, key, value).Validate("Failed to set attribute"); + } + + internal void Set(string key, int value) + { + EngineConfig.SetInt(Handle, key, value).Validate("Failed to set attribute"); + } + + + internal void Set(string key, bool value) + { + EngineConfig.SetBool(Handle, key, value).Validate("Failed to set attribute"); + } + + internal void Set(string key, string value) + { + EngineConfig.SetString(Handle, key, value).Validate("Failed to set attribute"); + } + + internal int GetInt(string key) + { + int value = 0; + EngineConfig.GetInt(Handle, key, out value).Validate("Failed to get the value"); + return value; + } + + internal double GetDouble(string key) + { + double value = 0; + EngineConfig.GetDouble(Handle, key, out value).Validate("Failed to get the value"); + return value; + } + + internal bool GetBool(string key) + { + bool value = false; + EngineConfig.GetBool(Handle, key, out value).Validate("Failed to get the value"); + return value; + } + + internal string GetString(string key) + { + IntPtr ptr = IntPtr.Zero; + + try + { + EngineConfig.GetString(Handle, key, out ptr).Validate("Failed to get the value"); + return Marshal.PtrToStringAnsi(ptr); + } + finally + { + LibcSupport.Free(ptr); + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + EngineConfig.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(EngineConfiguration)); + } + return _handle; + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ErrorCorrectionLevel.cs b/src/Tizen.Multimedia.Vision/MediaVision/ErrorCorrectionLevel.cs new file mode 100755 index 0000000..7388c4f --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ErrorCorrectionLevel.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the supported QR code error correction level. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum ErrorCorrectionLevel + { + /// <summary> + /// Recovery up to 7% losses. + /// </summary> + /// <since_tizen> 3</since_tizen> + Low, + /// <summary> + /// Recovery up to 15% losses. + /// </summary> + /// <since_tizen> 3</since_tizen> + Medium, + /// <summary> + /// Recovery up to 25% losses. + /// </summary> + /// <since_tizen> 3</since_tizen> + Quartile, + /// <summary> + /// Recovery up to 30% losses. + /// </summary> + /// <since_tizen> 3</since_tizen> + High + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/EyeCondition.cs b/src/Tizen.Multimedia.Vision/MediaVision/EyeCondition.cs new file mode 100755 index 0000000..7cf912f --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/EyeCondition.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the eyes state types. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum EyeCondition + { + /// <summary> + /// Eyes are open. + /// </summary> + /// <since_tizen> 3</since_tizen> + Open, + + /// <summary> + /// Eyes are closed. + /// </summary> + /// <since_tizen> 3</since_tizen> + Closed, + + /// <summary> + /// The eyes condition wasn't determined. + /// </summary> + /// <since_tizen> 3</since_tizen> + NotFound + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceDetectionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceDetectionConfiguration.cs new file mode 100755 index 0000000..cd08d30 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceDetectionConfiguration.cs @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="FaceDetector"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceDetectionConfiguration : EngineConfiguration + { + private const string KeyModelFilePath = "MV_FACE_DETECTION_MODEL_FILE_PATH"; + private const string KeyRoiX = "MV_FACE_DETECTION_ROI_X"; + private const string KeyRoiY = "MV_FACE_DETECTION_ROI_Y"; + private const string KeyRoiWidth = "MV_FACE_DETECTION_ROI_WIDTH"; + private const string KeyRoiHeight = "MV_FACE_DETECTION_ROI_HEIGHT"; + private const string KeyMinWidth = "MV_FACE_DETECTION_MIN_SIZE_WIDTH"; + private const string KeyMinHeight = "MV_FACE_DETECTION_MIN_SIZE_HEIGHT"; + + /// <summary> + /// Initializes a new instance of the <see cref="FaceDetectionConfiguration"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public FaceDetectionConfiguration() : base("face_recognition") + { + } + + /// <summary> + /// Gets or sets the face detection haarcascade xml file for face detection. + /// </summary> + /// <exception cref="ArgumentNullException"><paramref name="value"/> is null.</exception> + /// <since_tizen> 3</since_tizen> + public string ModelFilePath + { + get + { + return GetString(KeyModelFilePath); + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(ModelFilePath), "ModeFilePath can't be null."); + } + Set(KeyModelFilePath, value); + } + } + + + /// <summary> + /// Gets or sets minimum height of face which will be detected. + /// </summary> + /// <remarks> + /// Default value is null (all detected faces will be applied), can be changed to specify the minimum face height. + /// </remarks> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <since_tizen> 3</since_tizen> + public int? MinHeight + { + get + { + int value = GetInt(KeyMinHeight); + if (value == -1) return null; + return value; + } + set + { + if (value.HasValue && value < 0) + { + throw new ArgumentOutOfRangeException(nameof(MinHeight), value, + $"{nameof(MinHeight)} can't be less than zero."); + } + + Set(KeyMinHeight, value ?? -1); + } + } + + /// <summary> + /// Gets or sets minimum width of face which will be detected. + /// </summary> + /// <remarks> + /// Default value is null (all detected faces will be applied), can be changed to specify the minimum face width. + /// </remarks> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <since_tizen> 3</since_tizen> + public int? MinWidth + { + get + { + int value = GetInt(KeyMinWidth); + if (value == -1) return null; + return value; + } + set + { + if (value.HasValue && value < 0) + { + throw new ArgumentOutOfRangeException(nameof(MinWidth), value, + $"{nameof(MinWidth)} can't be less than zero."); + } + + Set(KeyMinWidth, value ?? -1); + } + } + + private static readonly Rectangle DefaultRoi = new Rectangle(-1, -1, -1, -1); + + private Rectangle? _roi; + + /// <summary> + /// Gets or sets the roi of the face detection. + /// </summary> + /// <remarks> + /// Default value is null (the roi will be a full image) can be changed to specify the roi for face detection. + /// </remarks> + /// <exception cref="ArgumentOutOfRangeException"> + /// The width of <paramref name="value"/> is less than or equal to zero.\n + /// -or-\n + /// The height of <paramref name="value"/> is less than or equal to zero.\n + /// -or-\n + /// The x position of <paramref name="value"/> is less than zero.\n + /// -or-\n + /// The y position of <paramref name="value"/> is less than zero.\n + /// </exception> + /// <since_tizen> 3</since_tizen> + public Rectangle? Roi + { + get + { + return _roi; + } + set + { + if (value != null) + { + ValidateRoi(value.Value); + } + + SetRoi(value ?? DefaultRoi); + + _roi = value; + } + } + + private static void ValidateRoi(Rectangle roi) + { + if (roi.Width <= 0) + { + throw new ArgumentOutOfRangeException("Roi.Width", roi.Width, + "The width of roi can't be less than or equal to zero."); + } + + if (roi.Height <= 0) + { + throw new ArgumentOutOfRangeException("Roi.Height", roi.Height, + "The height of roi can't be less than or equal to zero."); + } + + if (roi.X < 0) + { + throw new ArgumentOutOfRangeException("Roi.X", roi.X, + "The x position of roi can't be less than zero."); + } + + if (roi.Y < 0) + { + throw new ArgumentOutOfRangeException("Roi.Y", roi.Y, + "The y position of roi can't be less than zero."); + } + } + + private void SetRoi(Rectangle roi) + { + Set(KeyRoiX, roi.X); + Set(KeyRoiY, roi.Y); + Set(KeyRoiWidth, roi.Width); + Set(KeyRoiHeight, roi.Height); + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceDetector.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceDetector.cs new file mode 100755 index 0000000..c99d966 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceDetector.cs @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Threading.Tasks; +using InteropFace = Interop.MediaVision.Face; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to detect faces on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class FaceDetector + { + + /// <summary> + /// Detects faces on the source.\n + /// Each time when DetectAsync is called, a set of the detected faces at the media source are received asynchronously. + /// </summary> + /// <param name="source">The source of the media where faces will be detected.</param> + /// <returns>A task that represents the asynchronous detect operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// The format of <paramref name="source"/> is not supported. + /// </exception> + /// <since_tizen> 3</since_tizen> + public static async Task<Rectangle[]> DetectAsync(MediaVisionSource source) + { + return await DetectAsync(source, null); + } + + /// <summary> + /// Detects faces on the source.\n + /// Each time when DetectAsync is called, a set of the detected faces at the media source are received asynchronously. + /// </summary> + /// <param name="source">The source of the media where faces will be detected.</param> + /// <param name="config">The configuration of engine will be used for detecting. This value can be null.</param> + /// <returns>A task that represents the asynchronous detect operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<Rectangle[]> DetectAsync(MediaVisionSource source, + FaceDetectionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + TaskCompletionSource<Rectangle[]> tcs = new TaskCompletionSource<Rectangle[]>(); + + using (var cb = ObjectKeeper.Get(GetCallback(tcs))) + { + InteropFace.Detect(source.Handle, EngineConfiguration.GetHandle(config), cb.Target). + Validate("Failed to perform face detection"); + + return await tcs.Task; + } + } + + private static InteropFace.DetectedCallback GetCallback(TaskCompletionSource<Rectangle[]> tcs) + { + return (IntPtr sourceHandle, IntPtr engineConfig, global::Interop.MediaVision.Rectangle[] facesLocations, + int numberOfFaces, IntPtr _) => + { + try + { + Log.Info(MediaVisionLog.Tag, $"Faces detected, count : {numberOfFaces}."); + Rectangle[] locations = new Rectangle[numberOfFaces]; + for (int i = 0; i < numberOfFaces; i++) + { + locations[i] = facesLocations[i].ToApiStruct(); + Log.Info(MediaVisionLog.Tag, $"Face {0} detected : {locations}."); + } + + if (!tcs.TrySetResult(locations)) + { + Log.Error(MediaVisionLog.Tag, "Failed to set face detection result."); + } + } + catch (Exception e) + { + MultimediaLog.Info(MediaVisionLog.Tag, "Failed to handle face detection.", e); + tcs.TrySetException(e); + } + }; + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionConfiguration.cs new file mode 100755 index 0000000..d3451f8 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionConfiguration.cs @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="FaceRecognizer"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceRecognitionConfiguration : EngineConfiguration + { + private const string KeyModelType = "MV_FACE_RECOGNITION_MODEL_TYPE"; + + /// <summary> + /// Initializes a new instance of the <see cref="FaceRecognitionConfiguration"/> class. + /// </summary> + /// <exception cref="System.NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public FaceRecognitionConfiguration() : base("face_recognition") + { + } + + /// <summary> + /// Gets or sets the method used for face recognition model learning. + /// Default value is <see cref="FaceRecognitionModelType.Lbph"/>. + /// </summary> + /// <exception cref="System.ArgumentException"><paramref name="value"/> is not valid.</exception> + /// <since_tizen> 3</since_tizen> + public FaceRecognitionModelType ModelType + { + get + { + return (FaceRecognitionModelType)GetInt(KeyModelType); + } + set + { + ValidationUtil.ValidateEnum(typeof(FaceRecognitionModelType), value); + Set(KeyModelType, (int)value); + } + } + + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModel.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModel.cs new file mode 100755 index 0000000..5b6a8bb --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModel.cs @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using System.Runtime.InteropServices; +using InteropModel = Interop.MediaVision.FaceRecognitionModel; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents the face recognition model interface. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceRecognitionModel : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="FaceRecognitionModel"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public FaceRecognitionModel() + { + InteropModel.Create(out _handle).Validate("Failed to create FaceRecognitionModel"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="FaceRecognitionModel"/> class withe the specified path. + /// </summary> + /// <remarks> + /// Models have been saved by <see cref="Save()"/> can be loaded. + /// </remarks> + /// <param name="modelPath">Path to the model to load.</param> + /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception> + /// <exception cref="FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <paramref name="modelPath"/> is not supported format. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception> + /// <seealso cref="Save(string)"/> + /// <since_tizen> 3</since_tizen> + public FaceRecognitionModel(string modelPath) + { + if (modelPath == null) + { + throw new ArgumentNullException(nameof(modelPath)); + } + + InteropModel.Load(modelPath, out _handle). + Validate("Failed to load FaceRecognitionModel from file"); + } + + ~FaceRecognitionModel() + { + Dispose(false); + } + + /// <summary> + /// Gets labels that had been learned by the model. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int[] Labels + { + get + { + IntPtr unmangedArray = IntPtr.Zero; + try + { + uint numOfLabels = 0; + + InteropModel.QueryLabels(Handle, out unmangedArray, out numOfLabels). + Validate("Failed to retrieve face labels."); + + int[] labels = new int[numOfLabels]; + Marshal.Copy(unmangedArray, labels, 0, (int)numOfLabels); + + return labels; + } + finally + { + if (unmangedArray != IntPtr.Zero) + { + LibcSupport.Free(unmangedArray); + } + } + } + } + + /// <summary> + /// Saves the recognition model to the file. + /// </summary> + /// <param name="path">Path to the file to save the model.</param> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception> + /// <since_tizen> 3</since_tizen> + public void Save(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + var ret = InteropModel.Save(path, Handle); + + if (ret == MediaVisionError.InvalidPath) + { + throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist."); + } + + ret.Validate("Failed to save recognition model to file"); + } + + private MediaVisionError InvokeAdd(MediaVisionSource source, int label, Rectangle? area) + { + if (area != null) + { + var rect = area.Value.ToMarshalable(); + return InteropModel.Add(source.Handle, Handle, ref rect, label); + } + + return InteropModel.Add(source.Handle, Handle, IntPtr.Zero, label); + } + + /// <summary> + /// Adds face image example to be used for face recognition model learning. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> that contains face image.</param> + /// <param name="label">The label that identifies face for which example is adding. + /// Specify the same labels for the face images of a single person when calling this method. + /// Has to be unique for each face.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="FaceRecognitionModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been dispose of. + /// </exception> + /// <seealso cref="Learn(FaceRecognitionConfiguration)"/> + /// <since_tizen> 3</since_tizen> + public void Add(MediaVisionSource source, int label) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + InvokeAdd(source, label, null).Validate("Failed to add face example image"); + } + + /// <summary> + /// Adds face image example to be used for face recognition model learning. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> that contains face image.</param> + /// <param name="label">The label that identifies face for which example is adding. + /// Specify the same labels for the face images of a single person when calling this method. + /// Has to be unique for each face.</param> + /// <param name="area">The rectangular region of the face image at the source image.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="FaceRecognitionModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been dispose of. + /// </exception> + /// <seealso cref="Learn(FaceRecognitionConfiguration)"/> + /// <since_tizen> 3</since_tizen> + public void Add(MediaVisionSource source, int label, Rectangle area) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + InvokeAdd(source, label, area).Validate("Failed to add face example image"); + } + + /// <summary> + /// Removes all face examples added with the specified label. + /// </summary> + /// <param name="label">The label that identifies face for which examples will be removed.</param> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <returns>true if the examples are successfully removed; otherwise, false if there is no example labeled with the specified label.</returns> + /// <seealso cref="Add(MediaVisionSource, int)"/> + /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/> + /// <since_tizen> 3</since_tizen> + public bool Remove(int label) + { + var ret = InteropModel.Remove(Handle, ref label); + + if (ret == MediaVisionError.KeyNotAvailable) + { + return false; + } + + ret.Validate("Failed to remove image example"); + return true; + } + + /// <summary> + /// Removes all face examples. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public void Reset() + { + InteropModel.Reset(Handle).Validate("Failed to reset image example"); + } + + + /// <summary> + /// Learns face recognition model. + /// </summary> + /// <remarks> + /// Before you start learning process, face recognition models has to be filled with training data - face image examples. + /// These examples has to be provided by <see cref="Add(MediaVisionSource, int)"/> or <see cref="Add(MediaVisionSource, int, Rectangle)"/>. + /// Recognition accuracy is usually increased when the different examples of the identical face are added more and more. + /// But it depends on the used learning algorithm. + /// </remarks> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <exception cref="InvalidOperationException">No examples added.</exception> + /// <seealso cref="Add(MediaVisionSource, int)"/> + /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/> + /// <since_tizen> 3</since_tizen> + public void Learn() + { + Learn(null); + } + + /// <summary> + /// Learns face recognition model with <see cref="FaceRecognitionConfiguration"/>. + /// </summary> + /// <remarks> + /// Before you start learning process, face recognition models has to be filled with training data - face image examples. + /// These examples has to be provided by <see cref="Add(MediaVisionSource, int)"/> or <see cref="Add(MediaVisionSource, int, Rectangle)"/>. + /// Recognition accuracy is usually increased when the different examples of the identical face are added more and more. + /// But it depends on the used learning algorithm. + /// </remarks> + /// <param name="config">The configuration used for learning of the recognition models. This value can be null.</param> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="FaceRecognitionModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="InvalidOperationException">No examples added.</exception> + /// <seealso cref="Add(MediaVisionSource, int)"/> + /// <seealso cref="Add(MediaVisionSource, int, Rectangle)"/> + /// <since_tizen> 3</since_tizen> + public void Learn(FaceRecognitionConfiguration config) + { + InteropModel.Learn(EngineConfiguration.GetHandle(config), Handle). + Validate("Failed to learn"); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + InteropModel.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(FaceRecognitionModel)); + } + return _handle; + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModelType.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModelType.cs new file mode 100755 index 0000000..f701f9e --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionModelType.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the face recognition model learning algorithms. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum FaceRecognitionModelType + { + /// <summary> + /// Eigenfaces. + /// </summary> + /// <since_tizen> 3</since_tizen> + EigenFaces = 1, + + /// <summary> + /// Fisherfaces. + /// </summary> + /// <since_tizen> 3</since_tizen> + FisherFaces, + + /// <summary> + /// Local Binary Patterns Histograms (LBPH); The default type. + /// </summary> + /// <since_tizen> 3</since_tizen> + Lbph + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionResult.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionResult.cs new file mode 100755 index 0000000..63d2fca --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognitionResult.cs @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents result of <see cref="FaceRecognizer"/> operations. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceRecognitionResult + { + internal FaceRecognitionResult(bool recognized, double confidence, int label, Rectangle? area) + { + Success = recognized; + Label = label; + Area = area; + Confidence = confidence; + } + + /// <summary> + /// Gets the value indicating the recognition is successful. + /// </summary> + /// <since_tizen> 3</since_tizen> + public bool Success { get; } + + /// <summary> + /// Gets the label of the recognized face. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int Label { get; } + + /// <summary> + /// Gets the location of the recognized face. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Rectangle? Area { get; } + + /// <summary> + /// The confidence of the recognition model that face has been recognized correctly (value from 0.0 to 1.0). + /// No faces were recognized if confidence was 0.0. When model has been learned on large amount of examples, + /// threshold for this value can be high (0.85-0.95). If model was learned for small amount of examples, + /// then threshold can be reduced (0.5-0.85). + /// </summary> + /// <since_tizen> 3</since_tizen> + public double Confidence { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognizer.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognizer.cs new file mode 100755 index 0000000..ba52619 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceRecognizer.cs @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using InteropFace = Interop.MediaVision.Face; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to recognize faces, face expressions and eye condition on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class FaceRecognizer + { + + /// <summary> + /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/>. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param> + /// <param name="recognitionModel">The <see cref="FaceRecognitionConfiguration"/> to be used for recognition.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="recognitionModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source, + FaceRecognitionModel recognitionModel) + { + return await InvokeRecognizeAsync(source, recognitionModel, null, null); + } + + /// <summary> + /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/> and a bounding box. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param> + /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param> + /// <param name="bound">Rectangular box bounding face image on the source.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="recognitionModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source, + FaceRecognitionModel recognitionModel, Rectangle bound) + { + return await InvokeRecognizeAsync(source, recognitionModel, bound, null); + } + + /// <summary> + /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/> and <see cref="FaceRecognitionConfiguration"/>. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param> + /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param> + /// <param name="config">The configuration used for recognition. This value can be null.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="recognitionModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source, + FaceRecognitionModel recognitionModel, FaceRecognitionConfiguration config) + { + return await InvokeRecognizeAsync(source, recognitionModel, null, config); + } + + + /// <summary> + /// Performs face recognition on the source with <see cref="FaceRecognitionModel"/>, <see cref="FaceRecognitionConfiguration"/> + /// and a bounding box. + /// </summary> + /// <param name="source">The <see cref="MediaVisionSource"/> of the media to recognize faces for.</param> + /// <param name="recognitionModel">The <see cref="FaceRecognitionModel"/> to be used for recognition.</param> + /// <param name="bound">Rectangular box bounding face image on the source.</param> + /// <param name="config">The <see cref="FaceRecognitionConfiguration"/> used for recognition. This value can be null.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="recognitionModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="InvalidOperationException"><paramref name="recognitionModel"/> is untrained model.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FaceRecognitionResult> RecognizeAsync(MediaVisionSource source, + FaceRecognitionModel recognitionModel, Rectangle bound, FaceRecognitionConfiguration config) + { + return await InvokeRecognizeAsync(source, recognitionModel, bound, config); + } + + private static MediaVisionError InvokeRecognize(IntPtr sourceHandle, IntPtr modelHandle, + IntPtr configHandle, InteropFace.RecognizedCallback cb, Rectangle? area) + { + if (area == null) + { + return InteropFace.Recognize(sourceHandle, modelHandle, configHandle, IntPtr.Zero, cb); + } + + var rect = area.Value.ToMarshalable(); + return InteropFace.Recognize(sourceHandle, modelHandle, configHandle, ref rect, cb); + } + + private static async Task<FaceRecognitionResult> InvokeRecognizeAsync(MediaVisionSource source, + FaceRecognitionModel recognitionModel, Rectangle? area, + FaceRecognitionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (recognitionModel == null) + { + throw new ArgumentNullException(nameof(recognitionModel)); + } + + TaskCompletionSource<FaceRecognitionResult> tcs = new TaskCompletionSource<FaceRecognitionResult>(); + + using (var cb = ObjectKeeper.Get(GetRecognizedCallback(tcs))) + { + InvokeRecognize(source.Handle, recognitionModel.Handle, EngineConfiguration.GetHandle(config), + cb.Target, area).Validate("Failed to perform face recognition."); + + return await tcs.Task; + } + } + + private static FaceRecognitionResult CreateRecognitionResult( + IntPtr faceLocationPtr, IntPtr faceLabelPtr, double confidence) + { + int faceLabel = 0; + if (faceLabelPtr != IntPtr.Zero) + { + faceLabel = Marshal.ReadInt32(faceLabelPtr); + } + + Rectangle? faceLocation = null; + if (faceLocationPtr != IntPtr.Zero) + { + var area = Marshal.PtrToStructure<global::Interop.MediaVision.Rectangle>(faceLocationPtr); + faceLocation = area.ToApiStruct(); + } + + return new FaceRecognitionResult(faceLabelPtr != IntPtr.Zero, confidence, faceLabel, faceLocation); + } + + private static InteropFace.RecognizedCallback GetRecognizedCallback( + TaskCompletionSource<FaceRecognitionResult> tcs) + { + return (IntPtr sourceHandle, IntPtr recognitionModelHandle, + IntPtr engineCfgHandle, IntPtr faceLocationPtr, IntPtr faceLabelPtr, double confidence, IntPtr _) => + { + try + { + if (!tcs.TrySetResult(CreateRecognitionResult(faceLocationPtr, faceLabelPtr, confidence))) + { + Log.Error(MediaVisionLog.Tag, "Failed to set result"); + } + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Setting recognition result failed.", e); + tcs.TrySetException(e); + } + }; + } + + /// <summary> + /// Determines eye-blink condition on media source. + /// </summary> + /// <param name="source">The source of the media to recognize eye-blink condition for.</param> + /// <param name="bound">The bounding the face at the source.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<EyeCondition> RecognizeEyeConditionAsync(MediaVisionSource source, + Rectangle bound) + { + return await RecognizeEyeConditionAsync(source, bound, null); + } + + /// <summary> + /// Determines eye-blink condition on media source. + /// </summary> + /// <param name="source">The source of the media to recognize eye-blink condition for.</param> + /// <param name="bound">The bounding the face at the source.</param> + /// <param name="config">The configuration used for eye-blink condition recognition. This value can be null.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<EyeCondition> RecognizeEyeConditionAsync(MediaVisionSource source, + Rectangle bound, FaceRecognitionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + TaskCompletionSource<EyeCondition> tcs = new TaskCompletionSource<EyeCondition>(); + + InteropFace.EyeConditionRecognizedCallback cb = (IntPtr sourceHandle, IntPtr engineCfgHandle, + global::Interop.MediaVision.Rectangle faceLocation, EyeCondition eyeCondition, IntPtr _) => + { + Log.Info(MediaVisionLog.Tag, $"Eye condition recognized, eye condition : {eyeCondition}"); + if (!tcs.TrySetResult(eyeCondition)) + { + Log.Error(MediaVisionLog.Tag, "Failed to set eye condition result"); + } + }; + + using (var cbKeeper = ObjectKeeper.Get(cb)) + { + InteropFace.RecognizeEyeCondition(source.Handle, EngineConfiguration.GetHandle(config), + bound.ToMarshalable(), cb).Validate("Failed to perform eye condition recognition."); + + return await tcs.Task; + } + } + + /// <summary> + /// Determines facial expression on media source. + /// </summary> + /// <param name="source">The source of the media to recognize facial expression for.</param> + /// <param name="bound">The location bounding the face at the source.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FacialExpression> RecognizeFacialExpressionAsync(MediaVisionSource source, + Rectangle bound) + { + return await RecognizeFacialExpressionAsync(source, bound, null); + } + + /// <summary> + /// Determines facial expression on media source. + /// </summary> + /// <param name="source">The source of the media to recognize facial expression for.</param> + /// <param name="bound">The location bounding the face at the source.</param> + /// <param name="config">The configuration used for expression recognition. This value can be null.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FacialExpression> RecognizeFacialExpressionAsync(MediaVisionSource source, + Rectangle bound, FaceRecognitionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + TaskCompletionSource<FacialExpression> tcsResult = new TaskCompletionSource<FacialExpression>(); + + InteropFace.MvFaceFacialExpressionRecognizedCallback cb = (IntPtr sourceHandle, IntPtr engineCfgHandle, + global::Interop.MediaVision.Rectangle faceLocation, FacialExpression facialExpression, IntPtr _) => + { + Log.Info(MediaVisionLog.Tag, $"Facial expression recognized, expression : {facialExpression}"); + if (!tcsResult.TrySetResult(facialExpression)) + { + Log.Error(MediaVisionLog.Tag, "Failed to set facial result"); + } + }; + + using (var cbKeeper = ObjectKeeper.Get(cb)) + { + InteropFace.RecognizeFacialExpression(source.Handle, EngineConfiguration.GetHandle(config), + bound.ToMarshalable(), cb). + Validate("Failed to perform facial expression recognition."); + + return await tcsResult.Task; + } + } + } +} + diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceTracker.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceTracker.cs new file mode 100755 index 0000000..4824579 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceTracker.cs @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using InteropFace = Interop.MediaVision.Face; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to track faces on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class FaceTracker + { + + /// <summary> + /// Performs face tracking on the source with the trackingModel. + /// </summary> + /// <param name="source">The source of the media to recognize face for.</param> + /// <param name="trackingModel">The model will be used for tracking.</param> + /// <param name="doLearn">The value indicating whether model learning while tracking. If it is true then model will try to learn + /// (if it supports learning feature), otherwise model will be not learned during the invoking tracking iteration. + /// Learning process improves tracking correctness, but can decrease tracking performance.</param> + /// <returns>A task that represents the asynchronous tracking operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="trackingModel"/> is null. + /// </exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="trackingModel"/> has already been disposed of. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="InvalidOperationException"><paramref name="trackingModel"/> is not prepared.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<FaceTrackingResult> TrackAsync(MediaVisionSource source, + FaceTrackingModel trackingModel, bool doLearn) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (trackingModel == null) + { + throw new ArgumentNullException(nameof(trackingModel)); + } + + TaskCompletionSource<FaceTrackingResult> tcs = new TaskCompletionSource<FaceTrackingResult>(); + + using (var cb = ObjectKeeper.Get(GetTrackCallback(tcs))) + { + InteropFace.Track(source.Handle, trackingModel.Handle, IntPtr.Zero, + cb.Target, doLearn).Validate("Failed to perform face tracking."); + + return await tcs.Task; + } + } + + private static InteropFace.TrackedCallback GetTrackCallback(TaskCompletionSource<FaceTrackingResult> tcs) + { + return (IntPtr sourceHandle, IntPtr trackingModelHandle, IntPtr engineCfgHandle, + IntPtr locationPtr, double confidence, IntPtr _) => + { + try + { + Quadrangle area = null; + if (locationPtr != IntPtr.Zero) + { + area = Marshal.PtrToStructure<global::Interop.MediaVision.Quadrangle>(locationPtr).ToApiStruct(); + } + + Log.Info(MediaVisionLog.Tag, $"Tracked area : {area}, confidence : {confidence}"); + + if (!tcs.TrySetResult(new FaceTrackingResult(locationPtr != IntPtr.Zero, confidence, area))) + { + Log.Error(MediaVisionLog.Tag, "Failed to set tracking result"); + } + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Setting tracking result failed.", e); + tcs.TrySetException(e); + } + }; + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingModel.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingModel.cs new file mode 100755 index 0000000..bc54478 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingModel.cs @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using InteropModel = Interop.MediaVision.FaceTrackingModel; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents face tracking model. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceTrackingModel : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="FaceTrackingModel"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public FaceTrackingModel() + { + InteropModel.Create(out _handle).Validate("Failed to create FaceTrackingModel."); + } + + /// <summary> + /// Initializes a new instance of the <see cref="FaceTrackingModel"/> class with the specified path. + /// </summary> + /// <remarks> + /// Models has been saved by <see cref="Save()"/> can be loaded. + /// </remarks> + /// <param name="modelPath">Path to the model to load.</param> + /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception> + /// <exception cref="FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <paramref name="modelPath"/> is not supported format. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception> + /// <seealso cref="Save()"/> + /// <since_tizen> 3</since_tizen> + public FaceTrackingModel(string modelPath) + { + if (modelPath == null) + { + throw new ArgumentNullException(nameof(modelPath)); + } + InteropModel.Load(modelPath, out _handle).Validate("Failed to load FaceTrackingModel from file."); + } + + ~FaceTrackingModel() + { + Dispose(false); + } + + private MediaVisionError InvokePrepare(MediaVisionSource source, Quadrangle region) + { + if (region != null) + { + var quad = region.ToMarshalable(); + return InteropModel.Prepare(Handle, IntPtr.Zero, source.Handle, ref quad); + } + + return InteropModel.Prepare(Handle, IntPtr.Zero, source.Handle, IntPtr.Zero); + } + + /// <summary> + /// Initializes tracking model by the location of the face to be tracked. + /// + /// It is usually called once after tracking model is created and each time before tracking + /// is started for the new sequence of sources which is not the direct continuation of + /// the sequence for which tracking has been performed before. But it is allowed to call it + /// between tracking sessions to allow Media Vision start to track more accurately. + /// </summary> + /// <remarks> + /// <paramref name="region"/> needs to be the position of the face to be tracked when called first time for the tracking model. + /// <paramref name="region"/> is fitted to the valid region of <paramref name="source"/> if <paramref name="region"/> has invalid points. + /// </remarks> + /// <param name="source">The source where face location is specified. + /// Usually it is the first frame of the video or the first image in the continuous + /// image sequence planned to be used for tracking.</param> + /// <param name="region">The region determining position of the face to be tracked on the source. + /// If null, then tracking model will try to find previously tracked face by itself.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="FaceTrackingModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already bean disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public void Prepare(MediaVisionSource source, Quadrangle region) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + InvokePrepare(source, region).Validate("Failed to prepare tracking model."); + } + + /// <summary> + /// Saves the tracking model to the file. + /// </summary> + /// <param name="path">Path to the file to save the model.</param> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception> + /// <since_tizen> 3</since_tizen> + public void Save(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + var ret = InteropModel.Save(path, Handle); + + if (ret == MediaVisionError.InvalidPath) + { + throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist."); + } + + ret.Validate("Failed to save tracking model to file"); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + InteropModel.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(FaceTrackingModel)); + } + return _handle; + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingResult.cs b/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingResult.cs new file mode 100755 index 0000000..3ee5f6b --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FaceTrackingResult.cs @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents result of face tracking operation. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class FaceTrackingResult + { + internal FaceTrackingResult(bool success, double confidence, Quadrangle region) + { + Success = success; + Confidence = confidence; + Region = region; + } + + /// <summary> + /// Gets the value indicating the recognition is successful. + /// </summary> + /// <since_tizen> 3</since_tizen> + public bool Success { get; } + + /// <summary> + /// Gets the region which determines new position of the tracked face on the source. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Quadrangle Region { get; } + + /// <summary> + /// The confidence of the tracking model that new location of the face was determined correctly + /// (value from 0.0 to 1.0). If no location was determined during last track iteration, then value is 0.0. + /// </summary> + /// <since_tizen> 3</since_tizen> + public double Confidence { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/FacialExpression.cs b/src/Tizen.Multimedia.Vision/MediaVision/FacialExpression.cs new file mode 100755 index 0000000..c136d97 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/FacialExpression.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the expression types for faces. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum FacialExpression + { + /// <summary> + /// Unknown face expression. + /// </summary> + /// <since_tizen> 3</since_tizen> + Unknown, + + /// <summary> + /// Face expression is neutral. + /// </summary> + /// <since_tizen> 3</since_tizen> + Neutral, + + /// <summary> + /// Face expression is smiling. + /// </summary> + /// <since_tizen> 3</since_tizen> + Smile, + + /// <summary> + /// Face expression is sadness. + /// </summary> + /// <since_tizen> 3</since_tizen> + Sadness, + + /// <summary> + /// Face expression is surprise. + /// </summary> + /// <since_tizen> 3</since_tizen> + Surprise, + + /// <summary> + /// Face expression is anger. + /// </summary> + /// <since_tizen> 3</since_tizen> + Anger, + + /// <summary> + /// Face expression is fear. + /// </summary> + /// <since_tizen> 3</since_tizen> + Fear, + + /// <summary> + /// Face expression is disgust. + /// </summary> + /// <since_tizen> 3</since_tizen> + Disgust + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageFillConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageFillConfiguration.cs new file mode 100755 index 0000000..3b22467 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageFillConfiguration.cs @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of fill operations of <see cref="ImageObject"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageFillConfiguration : EngineConfiguration + { + private const string KeyScaleFactor = "MV_IMAGE_RECOGNITION_OBJECT_SCALE_FACTOR"; + private const string KeyMaxKeypoints = "MV_IMAGE_RECOGNITION_OBJECT_MAX_KEYPOINTS_NUM"; + + /// <summary> + /// A read-only field that represents the default value of <see cref="ObjectScaleFactor"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultScaleFactor = 1.2; + + /// <summary> + /// A read-only field that represents the default value of <see cref="ObjectMaxKeyPoints"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultMaxKeypoints = 1000; + + /// <summary> + /// Initializes a new instance of the <see cref="ImageFillConfiguration"/> class. + /// </summary> + /// <exception cref="System.NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public ImageFillConfiguration() : base("image_recognition") + { + } + + /// <summary> + /// Gets or sets the scale factor the image to be recognized.\n + /// The value of the factor will be used for resizing of the images (objects) for recognition. + /// The default value is 1.2. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="ImageFillConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public double ObjectScaleFactor + { + get + { + return GetDouble(KeyScaleFactor); + } + set + { + Set(KeyScaleFactor, value); + } + } + + /// <summary> + /// Gets or sets the maximum key points should be detected on the image.\n + /// The maximal number of key points can be selected on the image object to calculate descriptors. + /// This key points will be used for image (object) recognition and has to be specified as integer number. + /// The default value is 1000. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="ImageFillConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public int ObjectMaxKeyPoints + { + get + { + return GetInt(KeyMaxKeypoints); + } + set + { + Set(KeyMaxKeypoints, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageObject.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageObject.cs new file mode 100755 index 0000000..e56967e --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageObject.cs @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using InteropImage = Interop.MediaVision.Image; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents an image object. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageObject : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="ImageObject"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public ImageObject() + { + InteropImage.Create(out _handle).Validate("Failed to create image object"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="ImageObject"/> class from the specified file. + /// </summary> + /// <remarks> + /// ImageObject has been saved by <see cref="Save()"/> can be loaded. + /// </remarks> + /// <param name="path">Path to the image object to load.</param> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="FileNotFoundException"><paramref name="path"/> is invalid.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <paramref name="path"/> is not supported file. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception> + /// <seealso cref="Save(string)"/> + /// <since_tizen> 3</since_tizen> + public ImageObject(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + InteropImage.Load(path, out _handle).Validate("Failed to load image object from file"); + } + + ~ImageObject() + { + Dispose(false); + } + + /// <summary> + /// Gets a value that determines how well an image object can be recognized. + /// </summary> + /// <remarks> + /// If recognition rate is too low, try to use another image or change some configuration parameters + /// and fill the image object again. + /// </remarks> + /// <value> + /// Recognition rate determines how well an image object can be recognized. This value can be from 0 to 1. + /// If the recognition rate is 0 object can not be recognized and the bigger it is the more likely to recognize the object. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageObject"/> has already been disposed of.</exception> + /// <seealso cref="ImageFillConfiguration"/> + /// <seealso cref="Fill(MediaVisionSource)"/> + /// <seealso cref="Fill(MediaVisionSource, ImageFillConfiguration)"/> + /// <seealso cref="Fill(MediaVisionSource, Rectangle)"/> + /// <seealso cref="Fill(MediaVisionSource, ImageFillConfiguration, Rectangle)"/> + /// <since_tizen> 3</since_tizen> + public double RecognitionRate + { + get + { + InteropImage.GetRecognitionRate(Handle, out var rate).Validate("Failed to get recognition rate"); + return rate; + } + } + + #region Methods + /// <summary> + /// Gets the label for the image object. + /// </summary> + /// <returns> + /// The label value if the <see cref="ImageObject"/> has label, otherwise null. + /// </returns> + /// <exception cref="ObjectDisposedException">The <see cref="ImageObject"/> has already been disposed of.</exception> + /// <seealso cref="SetLabel(int)"/> + /// <since_tizen> 3</since_tizen> + public int? GetLabel() + { + var ret = InteropImage.GetLabel(Handle, out var label); + + if (ret == MediaVisionError.NoData) + { + return null; + } + + ret.Validate("Failed to get label"); + return label; + } + + /// <summary> + /// Sets the label for the <see cref="ImageObject"/>. + /// </summary> + /// <seealso cref="GetLabel"/> + /// <since_tizen> 3</since_tizen> + public void SetLabel(int label) + { + InteropImage.SetLabel(Handle, label).Validate("Failed to set label"); + } + + /// <summary> + /// Fills the image object.\n + /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location. + /// </summary> + /// <param name="source">The source image where image object is depicted.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="ImageObject"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public void Fill(MediaVisionSource source) + { + InvokeFill(source, null, null); + } + + /// <summary> + /// Fills the image object.\n + /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location. + /// </summary> + /// <param name="source">The source image where image object is depicted.</param> + /// <param name="config">The configuration used for extract recognition data from source. This value can be null.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="ImageObject"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public void Fill(MediaVisionSource source, ImageFillConfiguration config) + { + InvokeFill(source, config, null); + } + + /// <summary> + /// Fills the image object.\n + /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location. + /// </summary> + /// <param name="source">The source image where image object is depicted.</param> + /// <param name="rect">Rectangular bound of the image object on the source image.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="ImageObject"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been disposed of.\n + /// </exception> + /// <since_tizen> 3</since_tizen> + public void Fill(MediaVisionSource source, Rectangle rect) + { + InvokeFill(source, null, rect); + } + + /// <summary> + /// Fills the image object.\n + /// Extracts data from @a source image which will be needed for recognition of depicted object in @a location. + /// </summary> + /// <param name="source">The source image where image object is depicted.</param> + /// <param name="config">The configuration used for extract recognition data from source. This value can be null.</param> + /// <param name="rect">Rectangular bound of the image object on the source image.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="ImageObject"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public void Fill(MediaVisionSource source, ImageFillConfiguration config, Rectangle rect) + { + InvokeFill(source, config, rect); + } + + private MediaVisionError InvokeFill(IntPtr source, IntPtr config, Rectangle? area) + { + if (area == null) + { + return InteropImage.Fill(Handle, config, source, IntPtr.Zero); + } + + var rect = area.Value.ToMarshalable(); + + return InteropImage.Fill(Handle, config, source, ref rect); + } + + private void InvokeFill(MediaVisionSource source, ImageFillConfiguration config, Rectangle? area) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + InvokeFill(source.Handle, EngineConfiguration.GetHandle(config), area). + Validate("Failed to fill the image object"); + } + + /// <summary> + /// Saves the image object. + /// </summary> + /// <param name="path">Path to the file to save the model.</param> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="FaceRecognitionModel"/> has already been disposed of.</exception> + /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception> + /// <since_tizen> 3</since_tizen> + public void Save(string path) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + var ret = InteropImage.Save(path, Handle); + + if (ret == MediaVisionError.InvalidPath) + { + throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist."); + } + + ret.Validate("Failed to save the image object"); + } + #endregion + + #region IDisposable-support + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + InteropImage.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(ImageObject)); + } + return _handle; + } + } + #endregion + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionConfiguration.cs new file mode 100755 index 0000000..15dbd2e --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionConfiguration.cs @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="ImageRecognizer"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageRecognitionConfiguration : EngineConfiguration + { + private const string KeySceneScaleFactor = "MV_IMAGE_RECOGNITION_SCENE_SCALE_FACTOR"; + private const string KeySceneMaxKeypoints = "MV_IMAGE_RECOGNITION_SCENE_MAX_KEYPOINTS_NUM"; + + private const string KeyMinKeypointsMatch = "MV_IMAGE_RECOGNITION_MIN_MATCH_NUM"; + private const string KeyReqMatchPartKey = "MV_IMAGE_RECOGNITION_REQ_MATCH_PART"; + private const string KeyTolerantPartMatchingError = "MV_IMAGE_RECOGNITION_TOLERANT_MATCH_PART_ERR"; + + /// <summary> + /// A read-only field that represents the default value of <see cref="KeySceneScaleFactor"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultSceneScaleFactor = 1.2; + + /// <summary> + /// A read-only field that represents the default value of <see cref="SceneMaxKeyPoints"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultSceneMaxKeypoints = 5000; + + /// <summary> + /// A read-only field that represents the default value of <see cref="MinKeyPointMatches"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultMinKeyPointMatches = 30; + + /// <summary> + /// A read-only field that represents the default value of <see cref="RequiredMatchingPart"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultRequiredMatchPart = 0.05; + + /// <summary> + /// A read-only field that represents the default value of <see cref="TolerantPartMatchError"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultTolerantPartMatchError = 0.1; + + /// <summary> + /// Initializes a new instance of the <see cref="ImageRecognitionConfiguration"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public ImageRecognitionConfiguration() : base("image_recognition") + { + } + + /// <summary> + /// Gets or sets the scene scale factor. + /// </summary> + /// <value> + /// The value indicating the factor will be used for resizing of the scene including the images (objects) for recognition. + /// The default is 1.2. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public double SceneScaleFactor + { + get + { + return GetDouble(KeySceneScaleFactor); + } + set + { + Set(KeySceneScaleFactor, value); + } + } + + /// <summary> + /// Gets or sets the maximum key points that should be detected on the scene. + /// The maximal number of key points can be selected on the scene including the images (objects) to calculate descriptors. + /// </summary> + /// <value> + /// The maximal key points for image recognition. + /// The default is 5000. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <since_tizen> 3</since_tizen> + public int SceneMaxKeyPoints + { + get + { + return GetInt(KeySceneMaxKeypoints); + } + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(SceneMaxKeyPoints), value, + $"{nameof(SceneMaxKeyPoints)} can't be less than zero."); + } + Set(KeySceneMaxKeypoints, value); + } + } + + /// <summary> + /// Gets or sets the minimum number of key points matches required for recognition. + /// </summary> + /// <value> + /// The minimal number of key points should be matched between an image and a scene for image objects recognition. + /// The default is 30. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <since_tizen> 3</since_tizen> + public int MinKeyPointMatches + { + get + { + return GetInt(KeyMinKeypointsMatch); + } + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(MinKeyPointMatches), value, + $"{nameof(MinKeyPointMatches)} can't be less than zero."); + } + Set(KeyMinKeypointsMatch, value); + } + } + + /// <summary> + /// Gets or sets the required matching part for the image recognition. + /// To recognize occluded or hidden an image by other images, required relative part of the matches in respect to the total + /// amount of matching keypoints required for image recognition. Too low value will result in unsustainable behavior, + /// but effect of object overlapping will be reduced. + /// </summary> + /// <value> + /// The value indicating required relative part of the matches; can be from 0 to 1, inclusive. + /// The default is 0.05. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="value"/> is less than zero.\n + /// -or-\n + /// <paramref name="value"/> is greater than one. + /// </exception> + /// <since_tizen> 3</since_tizen> + public double RequiredMatchingPart + { + get + { + return GetDouble(KeyReqMatchPartKey); + } + set + { + if (value < 0 || value > 1) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive,"); + } + Set(KeyReqMatchPartKey, value); + } + } + + /// <summary> + /// Gets or sets the part matching error for the image recognition.\n + /// Allowable error of matches number. + /// </summary> + /// <value> + /// The value indicating allowable error of matches; can be from 0 to 1, inclusive. + /// The default is 0.1. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageRecognitionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="value"/> is less than zero.\n + /// -or-\n + /// <paramref name="value"/> is greater than one. + /// </exception> + /// <since_tizen> 3</since_tizen> + public double TolerantPartMatchError + { + get + { + return GetDouble(KeyTolerantPartMatchingError); + } + set + { + if (value < 0 || value > 1) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive."); + } + + Set(KeyTolerantPartMatchingError, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionResult.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionResult.cs new file mode 100755 index 0000000..0eafa1a --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognitionResult.cs @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a result of RecognizeAsync operations of <see cref="ImageRecognizer"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageRecognitionResult + { + + internal ImageRecognitionResult(bool success, Quadrangle region) + { + Success = success; + Region = region; + } + + /// <summary> + /// The region of recognized image object on the source image. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Quadrangle Region { get; } + + /// <summary> + /// Gets the value indicating the recognition is successful. + /// </summary> + /// <since_tizen> 3</since_tizen> + public bool Success { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognizer.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognizer.cs new file mode 100755 index 0000000..ef9c27e --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageRecognizer.cs @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using InteropImage = Interop.MediaVision.Image; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to recognize images on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class ImageRecognizer + { + /// <summary> + /// Recognizes the given image objects on the source image.\n + /// </summary> + /// <param name="source">The source image on which image objects will be recognized.</param> + /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="imageObjects"/> is null.\n + /// -or-\n + /// <paramref name="imageObjects"/> contains null reference. + /// </exception> + /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync( + MediaVisionSource source, ImageObject[] imageObjects) + { + return await RecognizeAsync(source, imageObjects, null); + } + + /// <summary> + /// Recognizes the given image objects on the source image.\n + /// </summary> + /// <param name="source">The source image on which image objects will be recognized.</param> + /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param> + /// <param name="config">The configuration used for recognition. This value can be null.</param> + /// <returns>A task that represents the asynchronous recognition operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="imageObjects"/> is null.\n + /// -or-\n + /// <paramref name="imageObjects"/> contains null elements. + /// </exception> + /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(MediaVisionSource source, + ImageObject[] imageObjects, ImageRecognitionConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (imageObjects == null) + { + throw new ArgumentNullException(nameof(imageObjects)); + } + if (imageObjects.Length == 0) + { + throw new ArgumentException("No image object to recognize.", nameof(imageObjects)); + } + + var tcs = new TaskCompletionSource<IEnumerable<ImageRecognitionResult>>(); + + using (var cb = ObjectKeeper.Get(GetCallback(tcs))) + using (var imageHandles = ObjectKeeper.Get(GetHandles(imageObjects))) + { + InteropImage.Recognize(source.Handle, imageHandles.Target, imageHandles.Target.Length, + EngineConfiguration.GetHandle(config), cb.Target). + Validate("Failed to perform image recognition."); + + return await tcs.Task; + } + } + + private static ImageRecognitionResult[] CreateResults(IntPtr[] locations, uint numOfObjects) + { + ImageRecognitionResult[] results = new ImageRecognitionResult[numOfObjects]; + + for (int i = 0; i < numOfObjects; i++) + { + Quadrangle quadrangle = locations[i] != IntPtr.Zero ? + Marshal.PtrToStructure<global::Interop.MediaVision.Quadrangle>(locations[i]).ToApiStruct() : null; + + results[i] = new ImageRecognitionResult(locations[i] != IntPtr.Zero, quadrangle); + } + + return results; + } + + private static InteropImage.RecognizedCallback GetCallback( + TaskCompletionSource<IEnumerable<ImageRecognitionResult>> tcs) + { + return (IntPtr source, IntPtr engineConfig, IntPtr imageObjectHandles, + IntPtr[] locations, uint numOfObjects, IntPtr _) => + { + try + { + if (!tcs.TrySetResult(CreateResults(locations, numOfObjects))) + { + Log.Info(MediaVisionLog.Tag, "Failed to set recognition result"); + } + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle recognition result", e); + tcs.TrySetException(e); + } + }; + } + + private static IntPtr[] GetHandles(ImageObject[] imageObjects) + { + IntPtr[] imageHandles = new IntPtr[imageObjects.Length]; + for (int i = 0; i < imageObjects.Length; i++) + { + if (imageObjects[i] == null) + { + throw new ArgumentNullException($"{nameof(imageObjects)}[{i}]"); + } + + imageHandles[i] = imageObjects[i].Handle; + } + + return imageHandles; + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageTracker.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageTracker.cs new file mode 100755 index 0000000..bcf07c1 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageTracker.cs @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using InteropImage = Interop.MediaVision.Image; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to track images on image sources. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static class ImageTracker + { + /// <summary> + /// Tracks the given image tracking model on the current frame. + /// </summary> + /// <param name="source">The current image of sequence where image tracking model will be tracked.</param> + /// <param name="trackingModel">The image tracking model which processed as target of tracking.</param> + /// <returns>A task that represents the asynchronous tracking operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="trackingModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="trackingModel"/> has already been disposed of. + /// </exception> + /// <exception cref="ArgumentException"><paramref name="trackingModel"/> has no target.</exception> + /// <seealso cref="ImageTrackingModel.SetTarget(ImageObject)"/> + /// <since_tizen> 3</since_tizen> + public static async Task<Quadrangle> TrackAsync(MediaVisionSource source, + ImageTrackingModel trackingModel) + { + return await TrackAsync(source, trackingModel, null); + } + + /// <summary> + /// Tracks the given image tracking model on the current frame and <see cref="ImageTrackingConfiguration"/>. + /// </summary> + /// <param name="source">The current image of sequence where image tracking model will be tracked.</param> + /// <param name="trackingModel">The image tracking model which processed as target of tracking.</param> + /// <param name="config">The configuration used for tracking. This value can be null.</param> + /// <returns>A task that represents the asynchronous tracking operation.</returns> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="trackingModel"/> is null. + /// </exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ObjectDisposedException"> + /// <paramref name="source"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="trackingModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="ArgumentException"><paramref name="trackingModel"/> has no target.</exception> + /// <seealso cref="ImageTrackingModel.SetTarget(ImageObject)"/> + /// <since_tizen> 3</since_tizen> + public static async Task<Quadrangle> TrackAsync(MediaVisionSource source, + ImageTrackingModel trackingModel, ImageTrackingConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + if (trackingModel == null) + { + throw new ArgumentNullException(nameof(trackingModel)); + } + + TaskCompletionSource<Quadrangle> tcs = new TaskCompletionSource<Quadrangle>(); + + using (var cb = ObjectKeeper.Get(GetCallback(tcs))) + { + InteropImage.Track(source.Handle, trackingModel.Handle, EngineConfiguration.GetHandle(config), + cb.Target).Validate("Failed to perform image tracking."); + + return await tcs.Task; + } + } + + private static InteropImage.TrackedCallback GetCallback(TaskCompletionSource<Quadrangle> tcs) + { + return (IntPtr sourceHandle, IntPtr imageTrackingModelHandle, IntPtr engineCfgHandle, IntPtr locationPtr, IntPtr _) => + { + try + { + Quadrangle region = null; + if (locationPtr != IntPtr.Zero) + { + region = Marshal.PtrToStructure<global::Interop.MediaVision.Quadrangle>(locationPtr).ToApiStruct(); + } + + Log.Info(MediaVisionLog.Tag, $"Image tracked, region : {region}"); + + if (!tcs.TrySetResult(region)) + { + Log.Info(MediaVisionLog.Tag, "Failed to set track result"); + } + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle track result", e); + tcs.TrySetException(e); + } + }; + + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingConfiguration.cs new file mode 100755 index 0000000..042b64b --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingConfiguration.cs @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="ImageTracker"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageTrackingConfiguration : ImageRecognitionConfiguration + { + private const string KeyHistoryAmount = "MV_IMAGE_TRACKING_HISTORY_AMOUNT"; + private const string KeyExpectedOffset = "MV_IMAGE_TRACKING_EXPECTED_OFFSET"; + private const string KeyUseStabilization = "MV_IMAGE_TRACKING_USE_STABLIZATION"; + private const string KeyStabilizationTolerantShift = "MV_IMAGE_TRACKING_STABLIZATION_TOLERANT_SHIFT"; + private const string KeyStabilizationSpeed = "MV_IMAGE_TRACKING_STABLIZATION_SPEED"; + private const string KeyStabilizationAcceleration = "MV_IMAGE_TRACKING_STABLIZATION_ACCELERATION"; + + /// <summary> + /// A read-only field that represents the default value of <see cref="HistoryAmount"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultHistoryAmount = 3; + + /// <summary> + /// A read-only field that represents the default value of <see cref="ExpectedOffset"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultExpectedOffset = 0; + + /// <summary> + /// A read-only field that represents the default value of <see cref="IsStabilizationEnabled"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly bool DefaultStabilizationEnabled = true; + + /// <summary> + /// A read-only field that represents the default value of <see cref="StabilizationTolerantShift"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultStabilizationTolerantShift = 0.00006; + + /// <summary> + /// A read-only field that represents the default value of <see cref="StabilizationSpeed"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultStabilizationSpeed = 0.3; + + /// <summary> + /// A read-only field that represents the default value of <see cref="StabilizationAcceleration"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly double DefaultStabilizationAcceleration = 0.1; + + /// <summary> + /// Initializes a new instance of the <see cref="ImageTrackingConfiguration"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public ImageTrackingConfiguration() + { + } + + /// <summary> + /// Gets or sets the number of recognition results in the tracking history. + /// </summary> + /// <value> + /// The number of previous recognition results, which will influence the stabilization.\n + /// The default is 3. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <since_tizen> 3</since_tizen> + public int HistoryAmount + { + get + { + return GetInt(KeyHistoryAmount); + } + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(HistoryAmount), value, + $"{nameof(HistoryAmount)} can't be less than zero."); + } + Set(KeyHistoryAmount, value); + } + } + + /// <summary> + /// Gets or sets the expected tracking offset. + /// </summary> + /// <value> + /// Relative offset value, for which the object offset is expected (relative to the object size in the current frame).\n + /// The default is 0. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public double ExpectedOffset + { + get + { + return GetDouble(KeyExpectedOffset); + } + set + { + Set(KeyExpectedOffset, value); + } + } + + /// <summary> + /// Gets or sets the acceleration of the tracking stabilization. + /// </summary> + /// <value> + /// Acceleration will be used for image stabilization (relative to the distance from current location to stabilized location); + /// from 0 to 1, inclusive.\n + /// The default is 0.1. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="value"/> is less than zero.\n + /// -or-\n + /// <paramref name="value"/> is greater than one. + /// </exception> + /// <since_tizen> 3</since_tizen> + public double StabilizationAcceleration + { + get + { + return GetDouble(KeyStabilizationAcceleration); + } + set + { + if (value < 0 || value > 1) + { + throw new ArgumentOutOfRangeException(nameof(value), value, "Valid range is 0 to 1 inclusive."); + } + + Set(KeyStabilizationAcceleration, value); + } + } + + /// <summary> + /// Gets or sets the speed of the tracking stabilization. + /// </summary> + /// <value> + /// The start speed value used for image stabilization.\n + /// The default is 0.3. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public double StabilizationSpeed + { + get + { + return GetDouble(KeyStabilizationSpeed); + } + set + { + Set(KeyStabilizationSpeed, value); + } + } + + /// <summary> + /// Gets or sets the relative tolerant shift for the tracking stabilization. + /// </summary> + /// <value> + /// It is component of tolerant shift which will be ignored by stabilization process. + /// (this value is relative to the object size in the current frame). + /// Tolerant shift will be computed like R * S + C, where R is the value set to <see cref="StabilizationTolerantShift"/>, + /// S is the area of object location on frame, C is a constant value 1.3.\n + /// \n + /// The default is 0.00006. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public double StabilizationTolerantShift + { + get + { + return GetDouble(KeyStabilizationTolerantShift); + } + set + { + Set(KeyStabilizationTolerantShift, value); + } + } + + /// <summary> + /// Gets or sets the state of the contour stabilization during tracking process. + /// </summary> + /// <value> + /// true if the contour stabilization is enabled; otherwise, false.\n + /// The default is true. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public bool IsStabilizationEnabled + { + get + { + return GetBool(KeyUseStabilization); + } + set + { + Set(KeyUseStabilization, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingModel.cs b/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingModel.cs new file mode 100755 index 0000000..c727d28 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/ImageTrackingModel.cs @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using InteropModel = Interop.MediaVision.ImageTrackingModel; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents the image tracking model interface. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class ImageTrackingModel : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="ImageTrackingModel"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public ImageTrackingModel() + { + InteropModel.Create(out _handle).Validate("Failed to create FaceTrackingModel"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="ImageTrackingModel"/> class with the specified path. + /// </summary> + /// <remarks> + /// Model have been saved by <see cref="Save()"/> can be loaded. + /// </remarks> + /// <param name="modelPath">Path to the model to load.</param> + /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception> + /// <exception cref="FileNotFoundException"><paramref name="modelPath"/> is invalid.</exception> + /// <exception cref="NotSupportedException"> + /// The feature is not supported.\n + /// -or-\n + /// <paramref name="modelPath"/> is not supported format. + /// </exception> + /// <exception cref="UnauthorizedAccessException">No permission to access the specified file.</exception> + /// <seealso cref="Save()"/> + /// <since_tizen> 3</since_tizen> + public ImageTrackingModel(string modelPath) + { + if (modelPath == null) + { + throw new ArgumentNullException(nameof(modelPath)); + } + InteropModel.Load(modelPath, out _handle).Validate("Failed to load ImageTrackingModel from file"); + } + + ~ImageTrackingModel() + { + Dispose(false); + } + + /// <summary> + /// Sets target of image tracking model.\n + /// Sets image object which will be tracked by using tracking functionality with this tracking model. + /// </summary> + /// <param name="imageObject">Image object which will be set as the target for tracking.</param> + /// <exception cref="ArgumentNullException"><paramref name="imageObject"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="ImageTrackingModel"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="imageObject"/> has already been disposed of. + /// </exception> + /// <since_tizen> 3</since_tizen> + public void SetTarget(ImageObject imageObject) + { + if (imageObject == null) + { + throw new ArgumentNullException(nameof(imageObject)); + } + + InteropModel.SetTarget(imageObject.Handle, Handle). + Validate("Failed to set target of image tracking model"); + } + + /// <summary> + /// Refreshes the state of image tracking model.\n + /// Clears moving history and change state to undetected. It is usually called each time before tracking is started + /// for the new sequence of sources which is not the direct continuation of the sequence for which tracking has been performed before. + /// Tracking algorithm will try to find image by itself. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingModel"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public void Refresh() + { + InteropModel.Refresh(Handle, IntPtr.Zero).Validate("Failed to refresh state"); + } + + /// <summary> + /// Saves tracking model to the file. + /// </summary> + /// <param name="path">Path to the file to save the model.</param> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is null.</exception> + /// <exception cref="UnauthorizedAccessException">No permission to write to the specified path.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="ImageTrackingModel"/> has already been disposed of.</exception> + /// <exception cref="DirectoryNotFoundException">The directory for <paramref name="path"/> does not exist.</exception> + /// <since_tizen> 3</since_tizen> + public void Save(string path) + { + if (path == null) + { + throw new ArgumentNullException(path); + } + + var ret = InteropModel.Save(path, Handle); + + if (ret == MediaVisionError.InvalidPath) + { + throw new DirectoryNotFoundException($"The directory for the path({path}) does not exist."); + } + + ret.Validate("Failed to save tracking model to file"); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + InteropModel.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(ImageTrackingModel)); + } + return _handle; + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionError.cs b/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionError.cs new file mode 100755 index 0000000..8298cfd --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionError.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.IO; +using Tizen.Internals.Errors; + +namespace Tizen.Multimedia +{ + internal static class MediaVisionLog + { + internal const string Tag = "Tizen.Multimedia.MediaVision"; + } + + /// <summary> + /// Enumeration for media vision's error codes. + /// </summary> + internal enum MediaVisionError + { + MediaVisionErrorCode = -0x019D0000, + /// <summary> + /// Successful + /// </summary> + None = ErrorCode.None, + /// <summary> + /// Not supported + /// </summary> + NotSupported = ErrorCode.NotSupported, + /// <summary> + /// Message too long + /// </summary> + MsgTooLong = ErrorCode.MsgTooLong, + /// <summary> + /// No data + /// </summary> + NoData = ErrorCode.NoData, + /// <summary> + /// Key not available + /// </summary> + KeyNotAvailable = ErrorCode.KeyNotAvailable, + /// <summary> + /// Out of memory + /// </summary> + OutOfMemory = ErrorCode.OutOfMemory, + /// <summary> + /// Invalid parameter + /// </summary> + InvalidParameter = ErrorCode.InvalidParameter, + /// <summary> + /// Invalid operation + /// </summary> + InvalidOperation = ErrorCode.InvalidOperation, + /// <summary> + /// Permission denied + /// </summary> + PermissionDenied = ErrorCode.NotPermitted, + /// <summary> + /// Not supported format + /// </summary> + NotSupportedFormat = MediaVisionErrorCode | 0x01, + /// <summary> + /// Internal error + /// </summary> + Internal = MediaVisionErrorCode | 0x02, + /// <summary> + /// Invalid data + /// </summary> + InvalidData = MediaVisionErrorCode | 0x03, + /// <summary> + /// Invalid path (Since 3.0) + /// </summary> + InvalidPath = MediaVisionErrorCode | 0x04 + } + + internal static class MediaVisionErrorExtensions + { + public static void Validate(this MediaVisionError error, string msg) + { + if (error == MediaVisionError.None) + { + return; + } + + switch (error) + { + case MediaVisionError.NotSupported: + throw new NotSupportedException(msg); + case MediaVisionError.MsgTooLong: + throw new ArgumentException($"{msg} : Message too long."); + case MediaVisionError.NoData: + throw new InvalidOperationException($"{msg} : No Data."); + case MediaVisionError.KeyNotAvailable: + throw new ArgumentException($"{msg} : Key Not Available."); + case MediaVisionError.OutOfMemory: + throw new OutOfMemoryException($"{msg} : Out of Memory."); + case MediaVisionError.InvalidParameter: + throw new ArgumentException($"{msg} : Invalid argument."); + case MediaVisionError.InvalidOperation: + throw new InvalidOperationException($"{msg} : Invalid Operation."); + case MediaVisionError.PermissionDenied: + throw new UnauthorizedAccessException($"{msg} : Permission Denied."); + case MediaVisionError.NotSupportedFormat: + throw new NotSupportedException($"{msg} : Not Supported Format."); + case MediaVisionError.Internal: + throw new InvalidOperationException($"{msg} : Internal Error."); + case MediaVisionError.InvalidData: + throw new ArgumentException($"{msg} : Invalid Data."); + case MediaVisionError.InvalidPath: + throw new FileNotFoundException($"{msg} : Invalid Path."); + default: + throw new InvalidOperationException($"{msg} : Unknown Error."); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionSource.cs b/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionSource.cs new file mode 100755 index 0000000..3bb4c2f --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/MediaVisionSource.cs @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Diagnostics; +using InteropSource = Interop.MediaVision.MediaSource; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents the media vision source to keep information on image or video frame data as raw buffer. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class MediaVisionSource : IBufferOwner, IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + internal MediaVisionSource() + { + InteropSource.Create(out _handle).Validate("Failed to create media vision source"); + } + + private MediaVisionSource(Action<IntPtr> fillAction) + : this() + { + try + { + fillAction(_handle); + } + catch(Exception) + { + InteropSource.Destroy(_handle); + _disposed = true; + throw; + } + } + + private static void FillMediaPacket(IntPtr handle, MediaPacket mediaPacket) + { + Debug.Assert(handle != IntPtr.Zero); + + if (mediaPacket == null) + { + throw new ArgumentNullException(nameof(mediaPacket)); + } + + InteropSource.FillMediaPacket(handle, mediaPacket.GetHandle()). + Validate("Failed to fill media packet"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MediaVisionSource"/> class based on the <see cref="MediaPacket"/>. + /// </summary> + /// <param name="mediaPacket">The <see cref="MediaPacket"/> from which the source will be filled.</param> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ArgumentNullException"><paramref name="mediaPacket"/> is null.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="mediaPacket"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public MediaVisionSource(MediaPacket mediaPacket) + : this(handle => FillMediaPacket(handle, mediaPacket)) + { + } + + private static void FillBuffer(IntPtr handle, byte[] buffer, uint width, uint height, Colorspace colorspace) + { + Debug.Assert(handle != IntPtr.Zero); + + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (buffer.Length == 0) + { + throw new ArgumentException("Buffer.Length is zero.", nameof(buffer)); + } + + if (colorspace == Colorspace.Invalid) + { + throw new ArgumentException($"color space must not be {Colorspace.Invalid}.", nameof(colorspace)); + } + + ValidationUtil.ValidateEnum(typeof(Colorspace), colorspace, nameof(colorspace)); + + InteropSource.FillBuffer(handle, buffer, buffer.Length, width, height, colorspace). + Validate("Failed to fill buffer"); + } + + /// <summary> + /// Initializes a new instance of the <see cref="MediaVisionSource"/> class based on the buffer and <see cref="Colorspace"/>. + /// </summary> + /// <param name="buffer">The buffer of image data.</param> + /// <param name="width">The width of image.</param> + /// <param name="height">The height of image.</param> + /// <param name="colorspace">The image <see cref="Colorspace"/>.</param> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <exception cref="ArgumentNullException"><paramref name="buffer"/> is null.</exception> + /// <exception cref="ArgumentException"> + /// <paramref name="buffer"/> has no element.(The length is zero.)\n + /// -or-\n + /// <paramref name="colorspace"/> is invalid. + /// </exception> + /// <since_tizen> 3</since_tizen> + public MediaVisionSource(byte[] buffer, uint width, uint height, Colorspace colorspace) + : this(handle => FillBuffer(handle, buffer, width, height, colorspace)) + { + } + + ~MediaVisionSource() + { + Dispose(false); + } + + private IMediaBuffer _buffer; + + /// <summary> + /// Gets the buffer of the media source. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public IMediaBuffer Buffer + { + get + { + if (_buffer == null) + { + IntPtr bufferHandle = IntPtr.Zero; + int bufferSize = 0; + + InteropSource.GetBuffer(Handle, out bufferHandle, out bufferSize). + Validate("Failed to get buffer"); + + _buffer = new DependentMediaBuffer(this, bufferHandle, bufferSize); + } + return _buffer; + } + } + + /// <summary> + /// Gets height of the media source. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public uint Height + { + get + { + uint height = 0; + var ret = InteropSource.GetHeight(Handle, out height); + MultimediaDebug.AssertNoError(ret); + return height; + } + } + + /// <summary> + /// Gets width of the media source. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public uint Width + { + get + { + uint width = 0; + var ret = InteropSource.GetWidth(Handle, out width); + MultimediaDebug.AssertNoError(ret); + return width; + } + } + + /// <summary> + /// Gets <see cref="Colorspace"/> of the media source. + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="MediaVisionSource"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public Colorspace Colorspace + { + get + { + Colorspace colorspace = Colorspace.Invalid; + var ret = InteropSource.GetColorspace(Handle, out colorspace); + MultimediaDebug.AssertNoError(ret); + return colorspace; + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + InteropSource.Destroy(_handle); + _disposed = true; + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(MediaVisionSource)); + } + return _handle; + } + } + + bool IBufferOwner.IsBufferAccessible(object buffer, MediaBufferAccessMode accessMode) + { + return true; + } + + bool IBufferOwner.IsDisposed + { + get { return _disposed; } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectedEventArgs.cs b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectedEventArgs.cs new file mode 100755 index 0000000..3456c5d --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectedEventArgs.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides data for the <see cref="MovementDetector.Detected"/> event. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class MovementDetectedEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="MovementDetectedEventArgs"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public MovementDetectedEventArgs(IEnumerable<Rectangle> areas) + { + Areas = areas; + } + + /// <summary> + /// Gets a set of rectangular regions where movement was detected. + /// </summary> + /// <since_tizen> 3</since_tizen> + public IEnumerable<Rectangle> Areas { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectionConfiguration.cs new file mode 100755 index 0000000..a9aebe8 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetectionConfiguration.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="MovementDetector"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class MovementDetectionConfiguration : SurveillanceEngineConfiguration + { + private const string KeyThreshold = "MV_SURVEILLANCE_MOVEMENT_DETECTION_THRESHOLD"; + + /// <summary> + /// A read-only field that represents the default value of <see cref="Threshold"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultThreshold = 10; + + + /// <summary> + /// Initializes a new instance of the <see cref="MovementDetectionConfiguration"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public MovementDetectionConfiguration() + { + } + + /// <summary> + /// Gets or sets movement detection threshold.\n + /// This value might be set before subscription on <see cref="MovementDetector.Detected"/> event + /// to specify the sensitivity of the movement detector. + /// </summary> + /// <value> + /// The value indicating the sensitivity of the <see cref="MovementDetector"/> from 0 to 255 inclusive + /// where 255 means that no movements will be detected and 0 means that all frame changes + /// will be interpreted as movements.\n + /// The default is 10. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="MovementDetectionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="value"/> is less than zero.\n + /// -or-\n + /// <paramref name="value"/> is greater than 255. + /// </exception> + /// <since_tizen> 3</since_tizen> + public int Threshold + { + get + { + return GetInt(KeyThreshold); + } + set + { + if (value < 0 || value > 255) + { + throw new ArgumentOutOfRangeException(nameof(Threshold), value, + $"Valid {nameof(Threshold)} range is 0 to 255 inclusive"); + } + + Set(KeyThreshold, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/MovementDetector.cs b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetector.cs new file mode 100755 index 0000000..d5861d0 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/MovementDetector.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using static Interop.MediaVision.Surveillance; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to detect movement on image sources. + /// </summary> + /// <seealso cref="MovementDetectionConfiguration"/> + /// <since_tizen> 3</since_tizen> + public class MovementDetector : SurveillanceEngine + { + private const string KeyNumberOfRegions = "NUMBER_OF_MOVEMENT_REGIONS"; + private const string KeyRegions = "MOVEMENT_REGIONS"; + + private const string MovementDetectedEventType = "MV_SURVEILLANCE_EVENT_MOVEMENT_DETECTED"; + + /// <summary> + /// Initializes a new instance of the <see cref="MovementDetector"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public MovementDetector() : base(MovementDetectedEventType) + { + } + + /// <summary> + /// Occurs when the movement detected. + /// </summary> + /// <remarks>The event handler will be executed on an internal thread.</remarks> + /// <since_tizen> 3</since_tizen> + public event EventHandler<MovementDetectedEventArgs> Detected; + + internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId, + IntPtr result, IntPtr _) + { + try + { + Detected?.Invoke(this, CreateMovementDetectedEventArgs(result)); + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e); + } + } + + private static Rectangle[] RetrieveAreas(IntPtr result) + { + int count = 0; + GetResultValue(result, KeyNumberOfRegions, out count).Validate("Failed to get result count"); + + if (count == 0) + { + return new Rectangle[0]; + } + + var rects = new global::Interop.MediaVision.Rectangle[count]; + + GetResultValue(result, KeyRegions, rects).Validate("Failed to get regions"); + + return global::Interop.ToApiStruct(rects); + } + + private static MovementDetectedEventArgs CreateMovementDetectedEventArgs(IntPtr result) + { + return new MovementDetectedEventArgs(RetrieveAreas(result)); + } + + + /// <summary> + /// Adds <see cref="SurveillanceSource"/>. + /// </summary> + /// <param name="source">The source used for recognition.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="MovementDetector"/> has already been disposed of.</exception> + /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public void AddSource(SurveillanceSource source) + { + AddSource(source, null); + } + + /// <summary> + /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="MovementDetectionConfiguration"/>. + /// </summary> + /// <param name="source">The source used for recognition.</param> + /// <param name="config">The config for the <paramref name="source"/>. This value can be null.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="MovementDetector"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public void AddSource(SurveillanceSource source, MovementDetectionConfiguration config) + { + InvokeAddSource(source, config); + } + + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectedEventArgs.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectedEventArgs.cs new file mode 100755 index 0000000..7c9576a --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectedEventArgs.cs @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides data for the <see cref="PersonAppearanceDetector.Detected"/> event. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class PersonAppearanceDetectedEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="PersonAppearanceDetectedEventArgs"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public PersonAppearanceDetectedEventArgs(IEnumerable<Rectangle> appeared, + IEnumerable<Rectangle> disappeared, IEnumerable<Rectangle> tracked) + { + AppearanceAreas = appeared; + DisappearanceAreas = disappeared; + TrackedAreas = tracked; + } + + /// <summary> + /// Gets a set of rectangular regions where appearances of the persons were detected. + /// </summary> + /// <since_tizen> 3</since_tizen> + public IEnumerable<Rectangle> AppearanceAreas { get; } + + /// <summary> + /// Gets a set of rectangular regions where disappearances of the persons were detected. + /// </summary> + /// <since_tizen> 3</since_tizen> + public IEnumerable<Rectangle> DisappearanceAreas { get; } + + /// <summary> + /// Gets a set of rectangular regions where persons were tracked. + /// </summary> + /// <since_tizen> 3</since_tizen> + public IEnumerable<Rectangle> TrackedAreas { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectionConfiguration.cs new file mode 100755 index 0000000..b4ef07b --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetectionConfiguration.cs @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="PersonAppearanceDetector"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class PersonAppearanceDetectionConfiguration : SurveillanceEngineConfiguration + { + private const string KeySkipFramesCount = "MV_SURVEILLANCE_SKIP_FRAMES_COUNT"; + + /// <summary> + /// A read-only field that represents the default value of <see cref="SkipFramesCount"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public static readonly int DefaultSkipFramesCount = 0; + + /// <summary> + /// Initializes a new instance of the <see cref="PersonAppearanceDetectionConfiguration"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public PersonAppearanceDetectionConfiguration() + { + } + + /// <summary> + /// Gets or sets how many frames will be skipped during push source.\n + /// </summary> + /// <value> + /// The value to specify the number of <see cref="MediaVisionSource"/> calls will be ignored by subscription + /// of the event trigger.\n + /// + /// The default is 0. It means that no frames will be skipped and all <see cref="MediaVisionSource"/> will + /// be processed. + /// </value> + /// <exception cref="ObjectDisposedException">The <see cref="PersonAppearanceDetectionConfiguration"/> already has been disposed of.</exception> + /// <exception cref="ArgumentOutOfRangeException"><paramref name="value"/> is less than zero.</exception> + /// <seealso cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public int SkipFramesCount + { + get + { + return GetInt(KeySkipFramesCount); + } + set + { + if (value < 0) + { + throw new ArgumentOutOfRangeException(nameof(SkipFramesCount), value, + $"{nameof(SkipFramesCount)} can't be less than zero."); + } + Set(KeySkipFramesCount, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetector.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetector.cs new file mode 100755 index 0000000..ef6d305 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonAppearanceDetector.cs @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using static Interop.MediaVision.Surveillance; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to detect person appearance changes on image sources. + /// </summary> + /// <seealso cref="PersonAppearanceDetectionConfiguration"/> + /// <since_tizen> 3</since_tizen> + public class PersonAppearanceDetector : SurveillanceEngine + { + private const string KeyAppearedNumber = "NUMBER_OF_APPEARED_PERSONS"; + private const string KeyDisappearedNumber = "NUMBER_OF_DISAPPEARED_PERSONS"; + private const string KeyTrackedNumber = "NUMBER_OF_TRACKED_PERSONS"; + private const string KeyAppearedLocations = "APPEARED_PERSONS_LOCATIONS"; + private const string KeyDisappearedLocations = "DISAPPEARED_PERSONS_LOCATIONS"; + private const string KeyTrackedLocations = "TRACKED_PERSONS_LOCATIONS"; + + private const string PersonAppearanceEventType = "MV_SURVEILLANCE_EVENT_PERSON_APPEARED_DISAPEARED"; + + /// <summary> + /// Initializes a new instance of the <see cref="PersonAppearanceDetector"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public PersonAppearanceDetector() : base(PersonAppearanceEventType) + { + } + + /// <summary> + /// Occurs when the any appearance changes detected. + /// </summary> + /// <remarks>The event handler will be executed on an internal thread.</remarks> + /// <since_tizen> 3</since_tizen> + public event EventHandler<PersonAppearanceDetectedEventArgs> Detected; + + internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId, + IntPtr result, IntPtr _) + { + try + { + Detected?.Invoke(this, CreatePersonAppearanceChangedEventArgs(result)); + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e); + } + } + + + private PersonAppearanceDetectedEventArgs CreatePersonAppearanceChangedEventArgs(IntPtr result) + { + return new PersonAppearanceDetectedEventArgs( + GetResultAreas(result, KeyAppearedNumber, KeyAppearedLocations), + GetResultAreas(result, KeyDisappearedNumber, KeyDisappearedLocations), + GetResultAreas(result, KeyTrackedNumber, KeyTrackedLocations) + ); + } + + private static Rectangle[] GetResultAreas(IntPtr result, string countKey, string regionsKey) + { + int count = 0; + GetResultValue(result, countKey, out count).Validate("Failed to get result"); + + var rects = new global::Interop.MediaVision.Rectangle[count]; + if (count > 0) + { + GetResultValue(result, regionsKey, rects).Validate("Failed to get result"); + } + + return global::Interop.ToApiStruct(rects); + } + + /// <summary> + /// Adds <see cref="SurveillanceSource"/>. + /// </summary> + /// <param name="source">The source used for recognition.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="PersonAppearanceDetector"/> has already been disposed of.</exception> + /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public void AddSource(SurveillanceSource source) + { + AddSource(source, null); + } + + /// <summary> + /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="PersonAppearanceDetectionConfiguration"/>. + /// </summary> + /// <param name="source">The source used for recognition.</param> + /// <param name="config">The config for the <paramref name="source"/>. This value can be null.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="PersonAppearanceDetector"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public void AddSource(SurveillanceSource source, PersonAppearanceDetectionConfiguration config) + { + InvokeAddSource(source, config); + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionConfiguration.cs new file mode 100755 index 0000000..867de87 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionConfiguration.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a configuration of <see cref="PersonRecognizer"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class PersonRecognitionConfiguration : SurveillanceEngineConfiguration + { + private const string KeyFaceRecognitionModelFilePath = "MV_SURVEILLANCE_FACE_RECOGNITION_MODEL_FILE_PATH"; + + /// <summary> + /// Initializes a new instance of the <see cref="PersonRecognitionConfiguration"/> class. + /// </summary> + /// <param name="modelPath">Path to the face recognition model.</param> + /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public PersonRecognitionConfiguration(string modelPath) + { + FaceRecognitionModelPath = modelPath; + } + + /// <summary> + /// Gets or sets face recognition model file path. + /// </summary> + /// <exception cref="ArgumentNullException"><paramref name="modelPath"/> is null.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="PersonRecognitionConfiguration"/> already has been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public string FaceRecognitionModelPath + { + get + { + return GetString(KeyFaceRecognitionModelFilePath); + } + set + { + if (value == null) + { + throw new ArgumentNullException(nameof(FaceRecognitionModelPath)); + } + Set(KeyFaceRecognitionModelFilePath, value); + } + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionInfo.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionInfo.cs new file mode 100755 index 0000000..a7589c8 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognitionInfo.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a result of <see cref="PersonRecognizer"/> instances. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class PersonRecognitionInfo + { + /// <summary> + /// Initializes a new instance of the <see cref="PersonRecognitionInfo"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public PersonRecognitionInfo(Rectangle area, int label, double confidence) + { + Area = area; + Label = label; + Confidence = confidence; + } + + /// <summary> + /// Gets the rectangular location where person face was recognized. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Rectangle Area { get; } + + /// <summary> + /// Gets the label that correspond to the recognized person. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int Label { get; } + + /// <summary> + /// Gets the confidence value that correspond to the recognized person. + /// </summary> + /// <since_tizen> 3</since_tizen> + public double Confidence { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizedEventArgs.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizedEventArgs.cs new file mode 100755 index 0000000..bbe65a9 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizedEventArgs.cs @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Collections.Generic; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides data for the <see cref="PersonRecognizer.Recognized"/> event. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class PersonRecognizedEventArgs : EventArgs + { + /// <summary> + /// Initializes a new instance of the <see cref="PersonRecognizedEventArgs"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public PersonRecognizedEventArgs(IEnumerable<PersonRecognitionInfo> recognitionInfo) + { + Recognitions = recognitionInfo; + } + + /// <summary> + /// Gets a set of information that correspond to the recognized persons. + /// </summary> + /// <since_tizen> 3</since_tizen> + public IEnumerable<PersonRecognitionInfo> Recognitions { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizer.cs b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizer.cs new file mode 100755 index 0000000..e14e38c --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/PersonRecognizer.cs @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using static Interop.MediaVision.Surveillance; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to recognize person on image sources. + /// </summary> + /// <seealso cref="PersonRecognitionConfiguration"/> + /// <since_tizen> 3</since_tizen> + public class PersonRecognizer : SurveillanceEngine + { + private const string KeyCount = "NUMBER_OF_PERSONS"; + private const string KeyLocations = "PERSONS_LOCATIONS"; + private const string KeyLabels = "PERSONS_LABELS"; + private const string KeyConfidences = "PERSONS_CONFIDENCES"; + + private const string PersonRecognizedEventType = "MV_SURVEILLANCE_EVENT_PERSON_RECOGNIZED"; + + /// <summary> + /// Initializes a new instance of the <see cref="PersonRecognizer"/> class. + /// </summary> + /// <exception cref="NotSupportedException">The feature is not supported.</exception> + /// <since_tizen> 3</since_tizen> + public PersonRecognizer() : base(PersonRecognizedEventType) + { + } + + /// <summary> + /// Occurs when a person recognized. + /// </summary> + /// <remarks>The event handler will be executed on an internal thread.</remarks> + /// <seealso cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/> + /// <since_tizen> 3</since_tizen> + public event EventHandler<PersonRecognizedEventArgs> Recognized; + + internal override void OnEventDetected(IntPtr trigger, IntPtr source, int streamId, + IntPtr result, IntPtr _) + { + try + { + Recognized?.Invoke(this, CreatePersonRecognizedEventArgs(result)); + } + catch (Exception e) + { + MultimediaLog.Error(MediaVisionLog.Tag, "Failed to invoke Recognized event.", e); + } + } + + private PersonRecognizedEventArgs CreatePersonRecognizedEventArgs(IntPtr result) + { + int count; + + GetResultValue(result, KeyCount, out count).Validate("Failed to get result count"); + + var recognitionInfo = new PersonRecognitionInfo[count]; + + if (count > 0) + { + var rects = new global::Interop.MediaVision.Rectangle[count]; + GetResultValue(result, KeyLocations, rects).Validate("Failed to get location"); + + var labels = new int[count]; + GetResultValue(result, KeyLabels, labels).Validate("Failed to get label"); + + var confidences = new double[count]; + GetResultValue(result, KeyConfidences, confidences).Validate("Failed to get confidence"); + + for (int i = 0; i < count; i++) + { + recognitionInfo[i] = new PersonRecognitionInfo(rects[i].ToApiStruct(), + labels[i], confidences[i]); + } + } + + return new PersonRecognizedEventArgs(recognitionInfo); + } + + /// <summary> + /// Adds <see cref="SurveillanceSource"/> with the provided <see cref="PersonRecognitionConfiguration"/>. + /// </summary> + /// <param name="source">The source used for recognition.</param> + /// <param name="config">The config for the <paramref name="source"/>.</param> + /// <exception cref="ArgumentNullException"> + /// <paramref name="source"/> is null.\n + /// -or-\n + /// <paramref name="config"/> is null. + /// </exception> + /// <exception cref="ObjectDisposedException"> + /// The <see cref="PersonRecognizer"/> has already been disposed of.\n + /// -or-\n + /// <paramref name="config"/> has already been disposed of. + /// </exception> + /// <exception cref="ArgumentException"> + /// <see cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/> of <paramref name="config"/> does not exists. + /// </exception> + /// <exception cref="UnauthorizedAccessException"> + /// No permission to access to the <see cref="PersonRecognitionConfiguration.FaceRecognitionModelPath"/>. + /// </exception> + /// <exception cref="NotSupportedException">The model file is not supported format or file.</exception> + /// <see cref="SurveillanceSource.Push(MediaVisionSource)"/> + /// <since_tizen> 3</since_tizen> + public void AddSource(SurveillanceSource source, PersonRecognitionConfiguration config) + { + if (config == null) + { + throw new ArgumentNullException(nameof(config)); + } + InvokeAddSource(source, config); + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/QrConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/QrConfiguration.cs new file mode 100755 index 0000000..b090a38 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/QrConfiguration.cs @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a QR configuration of <see cref="BarcodeGenerator"/>. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class QrConfiguration + { + /// <summary> + /// Initializes a new instance of the <see cref="QrConfiguration"/> class. + /// </summary> + /// <param name="qrMode">Encoding mode for the message.</param> + /// <param name="ecc">Error correction level.</param> + /// <param name="version">QR code version. From 1 to 40 inclusive.</param> + /// <code> + /// var obj = new QrConfiguration(QrMode.Numeric, ErrorCorrectionLevel.Medium, 30); + /// </code> + /// <exception cref="ArgumentOutOfRangeException"> + /// <paramref name="version"/> is less than 1.\n + /// -or-\n + /// <paramref name="version"/> is greater than 40. + /// </exception> + /// <exception cref="ArgumentException"> + /// <paramref name="qrMode"/> is invalid.\n + /// -or- + /// <paramref name="ecc"/> is invalid. + /// </exception> + /// <since_tizen> 3</since_tizen> + public QrConfiguration(QrMode qrMode, ErrorCorrectionLevel ecc, int version) + { + if (version < 1 || version > 40) + { + throw new ArgumentOutOfRangeException(nameof(version), version, + "Valid version range is 1 to 40 inclusive."); + } + ValidationUtil.ValidateEnum(typeof(QrMode), qrMode, nameof(qrMode)); + ValidationUtil.ValidateEnum(typeof(ErrorCorrectionLevel), ecc, nameof(ecc)); + + Mode = qrMode; + ErrorCorrectionLevel = ecc; + Version = version; + } + + /// <summary> + /// Gets the encoding mode for the message. + /// </summary> + /// <since_tizen> 3</since_tizen> + public QrMode Mode { get; } + + /// <summary> + /// Gets the error correction level. + /// </summary> + /// <since_tizen> 3</since_tizen> + public ErrorCorrectionLevel ErrorCorrectionLevel { get; } + + /// <summary> + /// Gets the QR code version. + /// </summary> + /// <since_tizen> 3</since_tizen> + public int Version { get; } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/QrMode.cs b/src/Tizen.Multimedia.Vision/MediaVision/QrMode.cs new file mode 100755 index 0000000..489a066 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/QrMode.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// Specifies the supported QR code encoding mode. + /// </summary> + /// <since_tizen> 3</since_tizen> + public enum QrMode + { + /// <summary> + /// Numeric digits. + /// </summary> + /// <since_tizen> 3</since_tizen> + Numeric, + /// <summary> + /// Alphanumeric characters, '$', '%', '*', '+', '-', '.', '/' and ':'. + /// </summary> + /// <since_tizen> 3</since_tizen> + AlphaNumeric, + /// <summary> + /// Raw 8-bit bytes. + /// </summary> + /// <since_tizen> 3</since_tizen> + Byte, + /// <summary> + /// UTF-8 character encoding. + /// </summary> + /// <since_tizen> 3</since_tizen> + Utf8 + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/Quadrangle.cs b/src/Tizen.Multimedia.Vision/MediaVision/Quadrangle.cs new file mode 100755 index 0000000..cc394c9 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/Quadrangle.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Represents a region with 4 <see cref="Point"/>s. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class Quadrangle + { + + /// <summary> + /// Initialize a new instance of the <see cref="Quadrangle"/> class with an array of <see cref="Point"/>. + /// </summary> + /// <remarks><paramref name="points"/> must have 4 elements.</remarks> + /// <param name="points">four points that define object bounding quadrangle.</param> + /// <exception cref="ArgumentException">The Length of <paramref name="points"/> is not 4.</exception> + /// <since_tizen> 3</since_tizen> + public Quadrangle(Point[] points) + { + if (points.Length != 4) + { + throw new ArgumentException($"{points} must have 4 elements."); + } + + Points = points; + } + + /// <summary> + /// Gets four points that define the object bounding quadrangle. + /// </summary> + /// <since_tizen> 3</since_tizen> + public Point[] Points { get; } + + public override string ToString() => + $"[{{{Points[0].ToString()}}}, {{{Points[1].ToString()}}}, {{{Points[2].ToString()}}}, {{{Points[3].ToString()}}}]"; + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceConfiguration.cs b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceConfiguration.cs new file mode 100755 index 0000000..a80ccc0 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceConfiguration.cs @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Tizen.Multimedia +{ + /// <summary> + /// SurveillanceEngineConfiguration is a base class for surveillance configurations. + /// </summary> + /// <since_tizen> 3</since_tizen> + public class SurveillanceEngineConfiguration : EngineConfiguration + { + internal SurveillanceEngineConfiguration() : base("face_recognition", "image_recognition") + { + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceEngine.cs b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceEngine.cs new file mode 100755 index 0000000..b06c503 --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceEngine.cs @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using System.Runtime.InteropServices; +using static Interop.MediaVision.Surveillance; + +namespace Tizen.Multimedia +{ + /// <summary> + /// SurveillanceEngine is a base class for surveillance event triggers. + /// Media Vision Surveillance provides functionality can be utilized for creation of video surveillance systems. + /// </summary> + /// <seealso cref="MovementDetector"/> + /// <seealso cref="PersonAppearanceDetector"/> + /// <seealso cref="PersonRecognizer"/> + /// <since_tizen> 3</since_tizen> + public abstract class SurveillanceEngine : IDisposable + { + private IntPtr _handle = IntPtr.Zero; + private bool _disposed = false; + + /// <summary> + /// Initializes a new instance of the <see cref="SurveillanceEngine"/> class. + /// </summary> + /// <param name="eventType">The type of the event trigger</param> + internal SurveillanceEngine(string eventType) + { + EventTriggerCreate(eventType, out _handle).Validate("Failed to create surveillance event trigger."); + } + + ~SurveillanceEngine() + { + Dispose(false); + } + + internal IntPtr Handle + { + get + { + if (_disposed) + { + throw new ObjectDisposedException(GetType().Name); + } + return _handle; + } + } + + /// <summary> + /// Sets and gets ROI (Region Of Interest). + /// </summary> + /// <exception cref="ObjectDisposedException">The <see cref="SurveillanceEngine"/> has already been disposed of.</exception> + /// <since_tizen> 3</since_tizen> + public Point[] Roi + { + get + { + IntPtr roiPtr = IntPtr.Zero; + try + { + int count = 0; + GetEventTriggerRoi(Handle, out count, out roiPtr).Validate("Failed to get roi"); + + Point[] points = new Point[count]; + IntPtr iterPtr = roiPtr; + + for (int i = 0; i < count; i++) + { + points[i] = Marshal.PtrToStructure<global::Interop.MediaVision.Point>(iterPtr).ToApiStruct(); + iterPtr = IntPtr.Add(iterPtr, Marshal.SizeOf<global::Interop.MediaVision.Point>()); + } + + return points; + } + finally + { + LibcSupport.Free(roiPtr); + } + } + set + { + int length = value == null ? 0 : value.Length; + + var points = value == null ? null : global::Interop.ToMarshalable(value); + + SetEventTriggerRoi(Handle, length, points).Validate("Failed to set roi"); + } + } + + internal abstract void OnEventDetected(IntPtr trigger, IntPtr source, + int streamId, IntPtr eventResult, IntPtr userData); + + internal void InvokeAddSource(SurveillanceSource source, SurveillanceEngineConfiguration config) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + SubscribeEventTrigger(Handle, source.StreamId, EngineConfiguration.GetHandle(config), + OnEventDetected).Validate("Failed to subscribe trigger"); + } + + /// <summary> + /// Removes the source from <see cref="SurveillanceEngine"/>. + /// </summary> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException">The <see cref="SurveillanceEngine"/> has already been disposed of.</exception> + /// <exception cref="ArgumentException"><paramref name="source"/> has not been added.</exception> + /// <since_tizen> 3</since_tizen> + public void RemoveSource(SurveillanceSource source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + UnsubscribeEventTrigger(Handle, source.StreamId).Validate("Failed to unsubscribe event trigger"); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + EventTriggerDestroy(_handle); + _disposed = true; + } + } +} diff --git a/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceSource.cs b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceSource.cs new file mode 100755 index 0000000..792243c --- /dev/null +++ b/src/Tizen.Multimedia.Vision/MediaVision/SurveillanceSource.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; +using static Interop.MediaVision.Surveillance; + +namespace Tizen.Multimedia +{ + /// <summary> + /// Provides the ability to push source to surveillance engines. + /// </summary> + /// <seealso cref="MovementDetector"/> + /// <seealso cref="PersonAppearanceDetector"/> + /// <seealso cref="PersonRecognizer"/> + /// <since_tizen> 3</since_tizen> + public class SurveillanceSource + { + private static int _nextStreamId = int.MinValue; + + private static int GetNextStreamId() + { + if (_nextStreamId == int.MaxValue) + { + return _nextStreamId = int.MinValue; + } + return _nextStreamId++; + } + + /// <summary> + /// Initializes a new instance of the <see cref="SurveillanceSource"/> class. + /// </summary> + /// <since_tizen> 3</since_tizen> + public SurveillanceSource() + { + StreamId = GetNextStreamId(); + } + + /// <summary> + /// Pushes source to the surveillance system to detect events. + /// </summary> + /// <param name="source">The media source used for surveillance.</param> + /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception> + /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception> + /// <exception cref="InvalidOperationException">This <see cref="SurveillanceSource"/> has not been added yet.</exception> + /// <seealso cref="MovementDetector.AddSource(SurveillanceSource)"/> + /// <seealso cref="MovementDetector.AddSource(SurveillanceSource, MovementDetectionConfiguration)"/> + /// <seealso cref="PersonAppearanceDetector.AddSource(SurveillanceSource)"/> + /// <seealso cref="PersonAppearanceDetector.AddSource(SurveillanceSource, PersonAppearanceDetectionConfiguration)"/> + /// <seealso cref="PersonRecognizer.AddSource(SurveillanceSource, PersonRecognitionConfiguration)"/> + /// <since_tizen> 3</since_tizen> + public void Push(MediaVisionSource source) + { + if (source == null) + { + throw new ArgumentNullException(nameof(source)); + } + + PushSource(source.Handle, StreamId).Validate("Failed to push source"); + } + + internal int StreamId { get; } + } +} |