[NUI] TCSACR-226 code change (#1032)
[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> 4 </since_tizen>
28     public static class ImageRecognizer
29     {
30         /// <summary>
31         /// Recognizes the given image objects on the source image.<br/>
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.<br/>
38         ///     -or-<br/>
39         ///     <paramref name="imageObjects"/> is null.<br/>
40         ///     -or-<br/>
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         /// <feature>http://tizen.org/feature/vision.image_recognition</feature>
47         /// <since_tizen> 4 </since_tizen>
48         public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(
49             MediaVisionSource source, ImageObject[] imageObjects)
50         {
51             return await RecognizeAsync(source, imageObjects, null);
52         }
53
54         /// <summary>
55         /// Recognizes the given image objects on the source image.<br/>
56         /// </summary>
57         /// <param name="source">The source image on which image objects will be recognized.</param>
58         /// <param name="imageObjects">The array of image objects which will be processed as targets of recognition.</param>
59         /// <param name="config">The configuration used for recognition. This value can be null.</param>
60         /// <returns>A task that represents the asynchronous recognition operation.</returns>
61         /// <exception cref="ArgumentNullException">
62         ///     <paramref name="source"/> is null.<br/>
63         ///     -or-<br/>
64         ///     <paramref name="imageObjects"/> is null.<br/>
65         ///     -or-<br/>
66         ///     <paramref name="imageObjects"/> contains null elements.
67         /// </exception>
68         /// <exception cref="ArgumentException"><paramref name="imageObjects"/> has no elements.(The length is zero.)</exception>
69         /// <exception cref="NotSupportedException">The feature is not supported.</exception>
70         /// <exception cref="ObjectDisposedException">
71         ///     <paramref name="source"/> has already been disposed of.<br/>
72         ///     -or-<br/>
73         ///     <paramref name="config"/> has already been disposed of.
74         /// </exception>
75         /// <feature>http://tizen.org/feature/vision.image_recognition</feature>
76         /// <since_tizen> 4 </since_tizen>
77         public static async Task<IEnumerable<ImageRecognitionResult>> RecognizeAsync(MediaVisionSource source,
78             ImageObject[] imageObjects, ImageRecognitionConfiguration config)
79         {
80             if (source == null)
81             {
82                 throw new ArgumentNullException(nameof(source));
83             }
84             if (imageObjects == null)
85             {
86                 throw new ArgumentNullException(nameof(imageObjects));
87             }
88             if (imageObjects.Length == 0)
89             {
90                 throw new ArgumentException("No image object to recognize.", nameof(imageObjects));
91             }
92
93             var tcs = new TaskCompletionSource<IEnumerable<ImageRecognitionResult>>();
94
95             using (var cb = ObjectKeeper.Get(GetCallback(tcs)))
96             using (var imageHandles = ObjectKeeper.Get(GetHandles(imageObjects)))
97             {
98                 InteropImage.Recognize(source.Handle, imageHandles.Target, imageHandles.Target.Length,
99                     EngineConfiguration.GetHandle(config), cb.Target).
100                     Validate("Failed to perform image recognition.");
101
102                 return await tcs.Task;
103             }
104         }
105
106         private static ImageRecognitionResult[] CreateResults(IntPtr[] locations, uint numOfObjects)
107         {
108             ImageRecognitionResult[] results = new ImageRecognitionResult[numOfObjects];
109
110             for (int i = 0; i < numOfObjects; i++)
111             {
112                 Quadrangle quadrangle = locations[i] != IntPtr.Zero ?
113                     Marshal.PtrToStructure<global::Interop.MediaVision.Quadrangle>(locations[i]).ToApiStruct() : null;
114
115                 results[i] = new ImageRecognitionResult(locations[i] != IntPtr.Zero, quadrangle);
116             }
117
118             return results;
119         }
120
121         private static InteropImage.RecognizedCallback GetCallback(
122             TaskCompletionSource<IEnumerable<ImageRecognitionResult>> tcs)
123         {
124             return (IntPtr source, IntPtr engineConfig, IntPtr imageObjectHandles,
125                 IntPtr[] locations, uint numOfObjects, IntPtr _) =>
126             {
127                 try
128                 {
129                     if (!tcs.TrySetResult(CreateResults(locations, numOfObjects)))
130                     {
131                         Log.Info(MediaVisionLog.Tag, "Failed to set recognition result");
132                     }
133                 }
134                 catch (Exception e)
135                 {
136                     MultimediaLog.Error(MediaVisionLog.Tag, "Failed to handle recognition result", e);
137                     tcs.TrySetException(e);
138                 }
139             };
140         }
141
142         private static IntPtr[] GetHandles(ImageObject[] imageObjects)
143         {
144             IntPtr[] imageHandles = new IntPtr[imageObjects.Length];
145             for (int i = 0; i < imageObjects.Length; i++)
146             {
147                 if (imageObjects[i] == null)
148                 {
149                     throw new ArgumentNullException($"{nameof(imageObjects)}[{i}]");
150                 }
151
152                 imageHandles[i] = imageObjects[i].Handle;
153             }
154
155             return imageHandles;
156         }
157     }
158 }