b96228572a2e609cb18f963e43ff507db077b70b
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.Vision / MediaVision / ImageRecognizer.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 using System;
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Threading.Tasks;
20 using InteropImage = Interop.MediaVision.Image;
21
22 namespace Tizen.Multimedia.Vision
23 {
24     /// <summary>
25     /// Provides the ability to recognize images on image sources.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public static class ImageRecognizer
29     {
30         /// <summary>
31         /// Recognizes the given image objects on the source image.\n
32         /// </summary>
33         /// <param name="source">The source image on which image objects will be recognized.</param>
34         /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param>
35         /// <returns>A task that represents the asynchronous recognition operation.</returns>
36         /// <exception cref="ArgumentNullException">
37         ///     <paramref name="source"/> is null.\n
38         ///     -or-\n
39         ///     <paramref name="imageObjects"/> is null.\n
40         ///     -or-\n
41         ///     <paramref name="imageObjects"/> contains null reference.
42         /// </exception>
43         /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception>
44         /// <exception cref="NotSupportedException">The feature is not supported.</exception>
45         /// <exception cref="ObjectDisposedException"><paramref name="source"/> has already been disposed of.</exception>
46         /// <since_tizen> 3 </since_tizen>
47         public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(
48             MediaVisionSource source, ImageObject[] imageObjects)
49         {
50             return await RecognizeAsync(source, imageObjects, null);
51         }
52
53         /// <summary>
54         /// Recognizes the given image objects on the source image.\n
55         /// </summary>
56         /// <param name="source">The source image on which image objects will be recognized.</param>
57         /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param>
58         /// <param name="config">The configuration used for recognition. This value can be null.</param>
59         /// <returns>A task that represents the asynchronous recognition operation.</returns>
60         /// <exception cref="ArgumentNullException">
61         ///     <paramref name="source"/> is null.\n
62         ///     -or-\n
63         ///     <paramref name="imageObjects"/> is null.\n
64         ///     -or-\n
65         ///     <paramref name="imageObjects"/> contains null elements.
66         /// </exception>
67         /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception>
68         /// <exception cref="NotSupportedException">The feature is not supported.</exception>
69         /// <exception cref="ObjectDisposedException">
70         ///     <paramref name="source"/> has already been disposed of.\n
71         ///     -or-\n
72         ///     <paramref name="config"/> has already been disposed of.
73         /// </exception>
74         /// <since_tizen> 3 </since_tizen>
75         public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(MediaVisionSource source,
76             ImageObject[] imageObjects, ImageRecognitionConfiguration config)
77         {
78             if (source == null)
79             {
80                 throw new ArgumentNullException(nameof(source));
81             }
82             if (imageObjects == null)
83             {
84                 throw new ArgumentNullException(nameof(imageObjects));
85             }
86             if (imageObjects.Length == 0)
87             {
88                 throw new ArgumentException("No image object to recognize.", nameof(imageObjects));
89             }
90
91             var tcs = new TaskCompletionSource<IEnumerable<ImageRecognitionResult>>();
92
93             using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
94             using (var imageHandles = ObjectKeeper.Get(GetHandles(imageObjects)))
95             {
96                 InteropImage.Recognize(source.Handle, imageHandles.Target, imageHandles.Target.Length,
97                     EngineConfiguration.GetHandle(config), cb.Target).
98                     Validate("Failed to perform image recognition.");
99
100                 return await tcs.Task;
101             }
102         }
103
104         private static ImageRecognitionResult[] CreateResults(IntPtr[] locations, uint numOfObjects)
105         {
106             ImageRecognitionResult[] results = new ImageRecognitionResult[numOfObjects];
107
108             for (int i = 0; i < numOfObjects; i++)
109             {
110                 Quadrangle quadrangle = locations[i] != IntPtr.Zero ?
111                     Marshal.PtrToStructure<global::Interop.MediaVision.Quadrangle>(locations[i]).ToApiStruct() : null;
112
113                 results[i] = new ImageRecognitionResult(locations[i] != IntPtr.Zero, quadrangle);
114             }
115
116             return results;
117         }
118
119         private static InteropImage.RecognizedCallback GetCallback(
120             TaskCompletionSource<IEnumerable<ImageRecognitionResult>> tcs)
121         {
122             return (IntPtr source, IntPtr engineConfig, IntPtr imageObjectHandles,
123                 IntPtr[] locations, uint numOfObjects, IntPtr _) =>
124             {
125                 try
126                 {
127                     if (!tcs.TrySetResult(CreateResults(locations, numOfObjects)))
128                     {
129                         Log.Info(MediaVisionLog.Tag, "Failed to set recognition result");
130                     }
131                 }
132                 catch (Exception e)
133                 {
134                     MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle recognition result", e);
135                     tcs.TrySetException(e);
136                 }
137             };
138         }
139
140         private static IntPtr[] GetHandles(ImageObject[] imageObjects)
141         {
142             IntPtr[] imageHandles = new IntPtr[imageObjects.Length];
143             for (int i = 0; i < imageObjects.Length; i++)
144             {
145                 if (imageObjects[i] == null)
146                 {
147                     throw new ArgumentNullException($"{nameof(imageObjects)}[{i}]");
148                 }
149
150                 imageHandles[i] = imageObjects[i].Handle;
151             }
152
153             return imageHandles;
154         }
155     }
156 }