/// <summary>
        /// Add the images in <c>images</c> to the hosted image collection.
        /// </summary>
        /// <remarks>
        /// <para>Returns the API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>add</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Empty array</description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="images">List of images with image data to add to collection.</param>
        /// <returns>The API JSON response with the image addition status.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the API 
        /// <c>add</c> request or parsing the response.</exception>
        public JObject AddImage(Image[] images)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < images.Length; i++)
                {
                    messageBuilder.Add("images[" + i + "]", images[i]);

                    if (images[i].CollectionFilepath != null)
                    {
                        messageBuilder.Add("filepaths[" + i + "]", images[i].CollectionFilepath);
                    }
                }

                return this.PostApiRequest("add", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("AddImage failed", e);
                throw new TinEyeServiceException("AddImage failed", e);
            }
        }
        /// <summary>
        /// Get counts for each color specified in a color palette (list of colors) from the
        /// images in the hosted image collection.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>count_collection_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>A color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>num_images_partial_area</term>
        ///                  <description>The number of input images that contain the palette color
        ///                  in any percentage</description></item>
        ///            <item><term>num_images_full_area</term>
        ///                  <description>The number of input images that contain the palette color 
        ///                  in a very large percentage</description>
        ///            </item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="countColors">The colors to be counted in the images.</param>
        /// <returns>The MulticolorEngine API JSON response with the extracted colors.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>count_collection_colors</c> request or parsing the response.
        /// </exception>
        public JObject CountCollectionColors(Color[] countColors)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < countColors.Length; i++)
                {
                    // Use RGB format for colors
                    string color = String.Format("{0},{1},{2}", new object[] { countColors[i].R, countColors[i].G, countColors[i].B });
                    messageBuilder.Add("count_colors[" + i + "]", color);
                }

                return this.PostApiRequest("count_collection_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CountCollectionColors failed", e);
                throw new TinEyeServiceException("CountCollectionColors failed", e);
            }
        }
        /// <summary>
        /// Extract the dominant colors in the hosted image collection filtered by
        /// image metadata. Metadata can be set to null to extract colors from all
        /// images in the collection.
        /// </summary>
        /// <remarks>
        /// <para>Color dominance is returned as a weight between 1 and 100 showing how much of the 
        /// color associated with the weight appears in the collection.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>extract_collection_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>The extracted color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>rank</term>
        ///                  <description>Integer value used to group images with similar color 
        ///                  palettes together. Results are sorted by rank</description></item>
        ///            <item><term>weight</term>
        ///                  <description>Float value between 1 and 100 indicating how much of that 
        ///                  color is in the collection</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="metadata">Metadata to use to filter the results, can be null.</param>
        /// <param name="limit">The maximum number of colors to be extracted.</param>
        /// <param name="colorFormat">To return, must be either rgb or hex.</param>
        /// <returns>The MulticolorEngine API JSON response with the extracted colors.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>extract_collection_colors</c> request or parsing the response.
        /// </exception>
        public JObject ExtractCollectionColorsMetadata(JObject metadata, int limit, string colorFormat)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                if (metadata != null)
                {
                    messageBuilder.Add("metadata", metadata.ToString());
                }
                messageBuilder.Add("limit",        limit);
                messageBuilder.Add("color_format", colorFormat);

                return this.PostApiRequest("extract_collection_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("ExtractCollectionColorsMetadata failed", e);
                throw new TinEyeServiceException("ExtractCollectionColorsMetadata failed", e);
            }
        }
        /// <summary>
        /// Extract the dominant colors given the filepaths of images in the hosted 
        /// image collection.
        /// </summary>
        /// <remarks>
        /// <para>Color dominance is returned as a weight between 1 and 100 showing how much of the 
        /// color associated with the weight appears in the image.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>extract_collection_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>The extracted color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>rank</term>
        ///                  <description>Integer value used to group images with similar color 
        ///                  palettes together. Results are sorted by rank</description></item>
        ///            <item><term>weight</term>
        ///                  <description>Float value between 1 and 100 indicating how much of that 
        ///                  color is in the collection</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="filepaths">Filepaths to images in the hosted image collection to 
        /// extract colors from.</param>
        /// <param name="limit">The maximum number of colors to be extracted.</param>
        /// <param name="colorFormat">To return, must be either rgb or hex.</param>
        /// <returns>The MulticolorEngine API JSON response with the extracted colors.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>extract_collection_colors</c> request or parsing the response.
        /// </exception>
        public JObject ExtractCollectionColorsFilepath(string[] filepaths, int limit, string colorFormat)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < filepaths.Length; i++)
                {
                    messageBuilder.Add("filepaths[" + i + "]", filepaths[i]);
                }
                messageBuilder.Add("limit",        limit);
                messageBuilder.Add("color_format", colorFormat);

                return this.PostApiRequest("extract_collection_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("ExtractCollectionColorsFilepath failed", e);
                throw new TinEyeServiceException("ExtractCollectionColorsFilepath failed", e);
            }
        }
        /// <summary>
        /// Extract the dominant colors in the hosted image collection filtered by colors.
        /// The colors passed in are used to get a set of images that have those colors, and
        /// then colors are extracted from that set of images and returned.
        /// </summary>
        /// <remarks>
        /// <para>Color dominance is returned as a weight between 1 and 100 showing
        /// how much of the color associated with the weight appears in the collection.</para>
        /// <para>Each passed in color may have an associated weight to indicate how much of a color
        /// should be in the set of images to extract colors from. If weights are included then 
        /// there must be one weight for each passed in color, each weight must be between
        /// 1 and 100 and all weights must add to 100.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>extract_collection_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>The extracted color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>rank</term>
        ///                  <description>Integer value used to group images with similar color 
        ///                  palettes together. Results are sorted by rank</description></item>
        ///            <item><term>weight</term>
        ///                  <description>Float value between 1 and 100 indicating how much of that 
        ///                  color is in the collection</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="colors">Array of colors used to filter the results.</param>
        /// <param name="weights">Array of color weights used to filter the results.</param>
        /// <param name="limit">The maximum number of colors to be extracted.</param>
        /// <param name="colorFormat">To return, must be either rgb or hex.</param>
        /// <returns>The MulticolorEngine API JSON response with the extracted colors.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>extract_collection_colors</c> request or parsing the response.
        /// </exception>
        public JObject ExtractCollectionColorsColors(Color[] colors, float[] weights, int limit, string colorFormat)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < colors.Length; i++)
                {
                    // Use RGB format for colors
                    string color = String.Format("{0},{1},{2}", new object[] { colors[i].R, colors[i].G, colors[i].B });
                    messageBuilder.Add("colors[" + i + "]", color);

                    if (weights.Length > 0)
                    {
                        messageBuilder.Add("weights[" + i + "]", weights[i]);
                    }
                }
                messageBuilder.Add("limit",        limit);
                messageBuilder.Add("color_format", colorFormat);

                return this.PostApiRequest("extract_collection_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("ExtractCollectionColorsColors failed", e);
                throw new TinEyeServiceException("ExtractCollectionColorsColors failed", e);
            }
        }
        /// <summary>
        /// Given one or more hosted image filepaths and metadata queries, get a counter
        /// specifying how many of the images from the specified filepaths match each query.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>count_metadata</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array with a single JSON object which has a metadata field
        ///         set to a list of JSON objects with the counts for each image from the 
        ///         given filepaths that match each metadata query passed in.
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="countMetadata">Array of metadata queries to get image counts for.</param>
        /// <param name="filepaths">Array of hosted image filepaths to get metadata counts for.
        /// </param>
        /// <returns>The MulticolorEngine API JSON response with the count of images matching
        /// each metadata query passed in.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>count_metadata</c> request or parsing the response.
        /// </exception>
        public JObject CountMetadataFilepaths(JObject[] countMetadata, string[] filepaths)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < countMetadata.Length; i++)
                {
                    messageBuilder.Add("count_metadata[" + i + "]", countMetadata[i].ToString());
                }

                for (int j = 0; j < filepaths.Length; j++)
                {
                    messageBuilder.Add("filepaths[" + j + "]", filepaths[j]);
                }

                return this.PostApiRequest("count_metadata", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CountMetadataFilepaths failed", e);
                throw new TinEyeServiceException("CountMetadataFilepaths failed", e);
            }
        }
Пример #7
0
        /// <summary>
        /// Add common search options to API POST request.
        /// </summary>
        /// <param name="messageBuilder">The messageBuilder being used to make the POST request.
        /// </param>
        /// <param name="metadata">Metadata to perform additional filtering on search results.
        /// </param>
        /// <param name="returnMetadata">Metadata fields to return with each match, which can
        /// include sorting options.</param>
        /// <param name="sortMetadata">If true, sort results by metadata score instead of by
        /// match score.</param>
        /// <param name="minScore">Minimum score of search results to return.</param>
        /// <param name="offset">Offset from start of search results to return.</param>
        /// <param name="limit">The maximum number of results to return.</param>
        /// <returns>The messageBuilder with all the passed in specified POST fields added.
        /// </returns>
        protected HttpMessageBuilder AddExtraSearchOptions(HttpMessageBuilder messageBuilder,
                                                           JObject metadata, JArray returnMetadata,
                                                           bool sortMetadata, int minScore,
                                                           int offset, int limit)
        {
            if (metadata != null)
            {
                messageBuilder.Add("metadata", metadata.ToString());
                messageBuilder.Add("return_metadata", returnMetadata.ToString());
                messageBuilder.Add("sort_metadata", sortMetadata);
            }

            messageBuilder.Add("min_score", minScore);
            messageBuilder.Add("offset", offset);
            messageBuilder.Add("limit", limit);

            return messageBuilder;
        }
        /// <summary>
        /// Search collection using an image URL and return any matches with corresponding scores.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MatchEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>search</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects for each match with the following fields:
        ///         <list type="table">
        ///            <item><term>score</term>
        ///                  <description>Relevance score of match</description></item>
        ///            <item><term>overlay</term>
        ///                  <description>URL pointing to the match overlay image on the API server
        ///                  </description></item>
        ///            <item><term>filepath</term>
        ///                  <description>The collection match filepath</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="url">The URL to the image to search for against the collection.</param>
        /// <param name="minScore">Minimum score to return for results.</param>
        /// <param name="offset">Offset to start returning results from.</param>
        /// <param name="limit">Maximum number of results to return.</param>
        /// <param name="checkHorizontalFlip">If true, also search for horizontally flipped image 
        /// in collection.</param>
        /// <returns>The MatchEngine API JSON response with search results.</returns>
        /// <exception cref="TinEyeServiceException">If exception occurs issuing the 
        /// MatchEngine API <c>search</c> request or parsing the response.</exception>
        public JObject SearchUrl(string url, int minScore, int offset, int limit, bool checkHorizontalFlip)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                messageBuilder.Add("url", url);
                messageBuilder.Add("min_score", minScore);
                messageBuilder.Add("offset", offset);
                messageBuilder.Add("limit", limit);
                messageBuilder.Add("check_horizontal_flip", checkHorizontalFlip);

                return this.PostApiRequest("search", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("SearchUrl failed", e);
                throw new TinEyeServiceException("SearchUrl failed", e);
            }
        }
        /// <summary>
        /// Upload a list of image URLs to the API and a color palette to get a count for
        /// each color specifying how many of the images at the given URLs contain that color.
        /// </summary>
        /// <remarks>
        /// <para>If the ignoreBackground option is set to true, an image region containing
        /// 75% or more of the image's edge pixels is considered a background region and its
        /// associated color is not counted. This is useful if you have an image of objects
        /// on a solid background color that you don't want to have counted.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>count_image_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>A color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>num_images_partial_area</term>
        ///                  <description>The number of input images that contain the palette color
        ///                  in any percentage</description></item>
        ///            <item><term>num_images_full_area</term>
        ///                  <description>The number of input images that contain the palette color 
        ///                  in a very large percentage</description>
        ///            </item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="imageUrls">The URLs to images to count colors from.</param>
        /// <param name="countColors">The colors to be counted in the images.</param>
        /// <param name="ignoreBackground">If true, ignore the background color of the images. 
        /// If false, include the background color of the images.</param>
        /// <param name="ignoreInteriorBackground">If true, ignore regions that have the 
        /// same color as the background region but that are surrounded by non-background regions.</param>
        /// <returns>The MulticolorEngine API JSON response with the count of palette colors
        /// in the passed in images.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the 
        /// MulticolorEngine API <c>count_image_colors</c> request or parsing the response.</exception>
        public JObject CountImageColorsUrl(string[] imageUrls, Color[] countColors, bool ignoreBackground, bool ignoreInteriorBackground)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < imageUrls.Length; i++)
                {
                    messageBuilder.Add("urls[" + i + "]", imageUrls[i]);
                }

                for (int i = 0; i < countColors.Length; i++)
                {
                    // Use RGB format for colors
                    string color = String.Format("{0},{1},{2}", new object[] { countColors[i].R, countColors[i].G, countColors[i].B });
                    messageBuilder.Add("count_colors[" + i + "]", color);
                }

                messageBuilder.Add("ignore_background",          ignoreBackground);
                messageBuilder.Add("ignore_interior_background", ignoreInteriorBackground);

                return this.PostApiRequest("count_image_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CountImageColorsUrl failed", e);
                throw new TinEyeServiceException("CountImageColorsUrl failed", e);
            }
        }
        /// <summary>
        /// Do a color search against the collection using an image URL and return matches with 
        /// corresponding scores.
        /// </summary>
        /// <remarks>
        /// <para>If the ignoreBackground option is set to true, an image region containing
        /// 75% or more of the image's edge pixels is considered a background region and its
        /// associated color is not included in the search.
        /// </para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>count</term>
        ///         <description>The number of search results</description></item>
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>color_search</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects for each match with the following fields:
        ///         <list type="table">
        ///            <item><term>score</term>
        ///                  <description>Relevance score of match</description></item>
        ///            <item><term>filepath</term>
        ///                  <description>The collection match filepath</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="imageUrl">URL to image whose colors to use for searching.</param>
        /// <param name="metadata">Metadata to perform additional filtering on search results.
        /// </param>
        /// <param name="returnMetadata">Metadata fields to return with each match, which can
        /// include sorting options.</param>
        /// <param name="sortMetadata">If true, sort results by metadata score instead of by
        /// match score.</param>
        /// <param name="ignoreBackground">If true, ignore the background color of the images. 
        /// If false, include the background color of the images.</param>
        /// <param name="ignoreInteriorBackground">If true, ignore regions that have the same 
        /// color as the background region but that are surrounded by non-background regions.</param>
        /// <param name="minScore">Minimum score of search results to return.</param>
        /// <param name="offset">Offset from start of search results to return.</param>
        /// <param name="limit">The maximum number of results to return.</param>
        /// <returns>The MulticolorEngine API JSON response with the color search results.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the 
        /// MulticolorEngine API <c>color_search</c> request or parsing the response.</exception>
        public JObject SearchUrl(string imageUrl, JObject metadata, JArray returnMetadata,
                                 bool sortMetadata, bool ignoreBackground, bool ignoreInteriorBackground,
                                 int minScore, int offset, int limit)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                messageBuilder.Add("url",                        imageUrl);
                messageBuilder.Add("ignore_background",          ignoreBackground);
                messageBuilder.Add("ignore_interior_background", ignoreInteriorBackground);

                messageBuilder = this.AddExtraSearchOptions(messageBuilder, metadata, returnMetadata,
                                                            sortMetadata, minScore, offset, limit);

                return this.PostApiRequest("color_search", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("SearchUrl failed", e);
                throw new TinEyeServiceException("SearchUrl failed", e);
            }
        }
        /// <summary>
        /// Search against the collection using metadata and return matches with
        /// corresponding scores.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>count</term>
        ///         <description>The number of search results</description></item>
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>color_search</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects for each match with the following fields:
        ///         <list type="table">
        ///            <item><term>metadata_score</term>
        ///                  <description>Relevance score of match based on metadata</description></item>
        ///            <item><term>filepath</term>
        ///                  <description>The collection match filepath</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="metadata">Metadata to perform filtering on search results.
        /// </param>
        /// <param name="returnMetadata">Metadata fields to return with each match, which can
        /// include sorting options.</param>
        /// <param name="sortMetadata">If true, sort results by metadata score instead of by
        /// match score.</param>
        /// <param name="minScore">Minimum score of search results to return.</param>
        /// <param name="offset">Offset from start of search results to return.</param>
        /// <param name="limit">The maximum number of results to return.</param>
        /// <returns>The MulticolorEngine API JSON response with the search results.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the 
        /// MulticolorEngine API <c>color_search</c> request or parsing the response.</exception>
        public JObject SearchMetadata(JObject metadata, JArray returnMetadata, bool sortMetadata, 
                                      int minScore, int offset, int limit)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                messageBuilder = this.AddExtraSearchOptions(messageBuilder, metadata, returnMetadata,
                                                            sortMetadata, minScore, offset, limit);

                return this.PostApiRequest("color_search", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("SearchMetadata failed", e);
                throw new TinEyeServiceException("SearchMetadata failed", e);
            }
        }
        /// <summary>
        /// Do a color search against the collection using specified colors and return matches with
        /// corresponding scores.
        /// </summary>
        /// <remarks>
        /// <para>Each color may have an associated weight, indicating how much of that color 
        /// should appear in a search result.</para>
        /// <note>If weights are used, there must be a weight for each color.</note>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>count</term>
        ///         <description>The number of search results</description></item>
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>color_search</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects for each match with the following fields:
        ///         <list type="table">
        ///            <item><term>score</term>
        ///                  <description>Relevance score of match</description></item>
        ///            <item><term>filepath</term>
        ///                  <description>The collection match filepath</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="colors">List of colors for searching the collection.</param>
        /// <param name="weights">List of weights corresponding to the colors, or empty list.
        /// </param>
        /// <param name="metadata">Metadata to perform additional filtering on search results.
        /// </param>
        /// <param name="returnMetadata">Metadata fields to return with each match, which can
        /// include sorting options.</param>
        /// <param name="sortMetadata">If true, sort results by metadata score instead of by
        /// match score.</param>
        /// <param name="minScore">Minimum score of search results to return.</param>
        /// <param name="offset">Offset from start of search results to return.</param>
        /// <param name="limit">The maximum number of results to return.</param>
        /// <returns>The MulticolorEngine API JSON response with the color search results.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the 
        /// MulticolorEngine API <c>color_search</c> request or parsing the response.</exception>
        public JObject SearchColor(Color[] colors, float[] weights, JObject metadata, JArray returnMetadata,
                                   bool sortMetadata, int minScore, int offset, int limit)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < colors.Length; i++)
                {
                    // Use RGB format for colors
                    string color = String.Format("{0},{1},{2}", new object[] { colors[i].R, colors[i].G, colors[i].B });
                    messageBuilder.Add("colors[" + i + "]", color);
                }

                for (int j = 0; j < weights.Length; j++)
                {
                    messageBuilder.Add("weights[" + j + "]", weights[j]);
                }

                messageBuilder = this.AddExtraSearchOptions(messageBuilder, metadata, returnMetadata,
                                                            sortMetadata, minScore, offset, limit);

                return this.PostApiRequest("color_search", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("SearchColor failed", e);
                throw new TinEyeServiceException("SearchColor failed", e);
            }
        }
        /// <summary>
        /// Delete images from the collection.
        /// </summary>
        /// <remarks>
        /// <para>Returns the API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>delete</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Empty array</description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="filepaths">Filepaths of images to delete as returned by a search or list 
        /// call.</param>
        /// <returns>The API JSON response with image deletion status.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the API 
        /// <c>delete</c> request or parsing the response.</exception>
        public JObject Delete(string[] filepaths)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < filepaths.Length; i++)
                {
                    messageBuilder.Add("filepaths[" + i + "]", filepaths[i]);
                }

                return this.PostApiRequest("delete", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("Delete failed", e);
                throw new TinEyeServiceException("Delete failed", e);
            }
        }
Пример #14
0
        /// <summary>
        /// Add the images in <c>images</c> to the hosted image collection.
        /// </summary>
        /// <remarks>
        /// <para>If the images have JSON metadata, add the images to the collection with metadata.
        /// </para>
        /// <note>If the metadata is included, each image must have metadata or the API will return
        /// an error.</note>
        /// <para>If the ignoreBackground option is set to true, an image region containing
        /// 75% or more of the image's edge pixels is considered a background region and its
        /// associated color is not included when indexing each image. This is mainly useful
        /// for product shots of objects on solid background colors. This option is not recommended 
        /// for collections containing images that don’t have solid color backgrounds like natural 
        /// images for example. 
        /// </para>
        /// <para>Returns the API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>add</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Empty array</description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="images">List of images to add to collection.</param>
        /// <param name="ignoreBackground">If true, ignore the background color of the images. 
        /// If false, include the background color of the images.</param>
        /// <param name="ignoreInteriorBackground">If true, ignore regions that have the 
        /// same color as the background region but that are surrounded by non-background regions.
        /// </param>
        /// <returns>The API JSON response with the status of the image addition.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the API 
        /// <c>add</c> request or parsing the response.</exception>
        public JObject AddImage(Image[] images, bool ignoreBackground, bool ignoreInteriorBackground)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < images.Length; i++)
                {
                    messageBuilder.Add("images[" + i + "]", images[i]);

                    if (images[i].CollectionFilepath != null)
                    {
                        messageBuilder.Add("filepaths[" + i + "]", images[i].CollectionFilepath);
                    }
                    if (images[i].Metadata != null)
                    {
                        messageBuilder.Add("metadata[" + i + "]", images[i].Metadata.ToString());
                    }
                }
                messageBuilder.Add("ignore_background",          ignoreBackground);
                messageBuilder.Add("ignore_interior_background", ignoreInteriorBackground);

                return this.PostApiRequest("add", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("AddImage failed", e);
                throw new TinEyeServiceException("AddImage failed", e);
            }
        }
        /// <summary>
        /// Extract the dominant colors from the images passed in.
        /// </summary>
        /// <remarks>
        /// <para>Color dominance is returned as a weight between 1 and 100 showing how much of the 
        /// color associated with the weight appears in the images.</para>
        /// <para>If the ignoreBackground option is set to true, an image region containing
        /// 75% or more of the image's edge pixels is considered a background region and its
        /// associated color is disgarded. This is useful if you have an image of objects
        /// on a solid background color that you don't want to have extracted.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>extract_image_colors</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects with the following fields:
        ///         <list type="table">
        ///            <item><term>color</term>
        ///                  <description>The extracted color in hex format, or an array with that 
        ///                  color's 3 RGB values</description></item>
        ///            <item><term>rank</term>
        ///                  <description>Integer value used to group images with similar color 
        ///                  palettes together. Results are sorted by rank</description></item>
        ///            <item><term>weight</term>
        ///                  <description>Float value between 1 and 100 indicating how much of that 
        ///                  color is in the images</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="images">The images to extract colors from.</param>
        /// <param name="limit">The maximum number of colors to be extracted.</param>
        /// <param name="ignoreBackground">If true, ignore the background color of the images. 
        /// If false, include the background color of the images.</param>
        /// <param name="ignoreInteriorBackground">If true, ignore regions that have the 
        /// same color as the background region but that are surrounded by non-background regions.</param>
        /// <param name="colorFormat">To be returned, must be either rgb or hex.</param>
        /// <returns>The MulticolorEngine API JSON response with the extracted colors.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the 
        /// MulticolorEngine API <c>extract_image_colors</c> request or parsing the response.</exception>
        public JObject ExtractImageColorsImage(Image[] images, int limit, bool ignoreBackground, bool ignoreInteriorBackground, string colorFormat)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < images.Length; i++)
                {
                    messageBuilder.Add("images[" + i + "]", images[i]);
                }
                messageBuilder.Add("limit",                      limit);
                messageBuilder.Add("ignore_background",          ignoreBackground);
                messageBuilder.Add("ignore_interior_background", ignoreInteriorBackground);
                messageBuilder.Add("color_format",               colorFormat);

                return this.PostApiRequest("extract_image_colors", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("ExtractImageColorsImage failed", e);
                throw new TinEyeServiceException("ExtractImageColorsImage failed", e);
            }
        }
        /// <summary>
        /// Compare the image at <c>url1</c> to the image at <c>url2</c> and return the match 
        /// score.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MatchEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>compare</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array of JSON objects for each match with the following fields:
        ///         <list type="table">
        ///            <item><term>score</term>
        ///                  <description>Relevance score of match</description></item>
        ///            <item><term>match_percent</term>
        ///                  <description>Percentage of images that matched</description></item>
        ///         </list>
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="url1">URL to the first image to compare.</param>
        /// <param name="url2">URL to the second image to compare.</param>
        /// <param name="minScore">The minimum score of the result to return.</param>
        /// <param name="checkHorizontalFlip">If true, also check if <c>image2</c> is the 
        /// horizontally flipped version of <c>image1</c></param>
        /// <returns>The MatchEngine API JSON response with compare results.</returns>
        /// <exception cref="TinEyeServiceException">If exception occurs issuing the 
        /// MatchEngine API <c>compare</c> request or parsing the response.</exception>
        public JObject CompareUrl(string url1, string url2, int minScore, bool checkHorizontalFlip)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                messageBuilder.Add("url1", url1);
                messageBuilder.Add("url2", url2);
                messageBuilder.Add("min_score", minScore);
                messageBuilder.Add("check_horizontal_flip", checkHorizontalFlip);

                return this.PostApiRequest("compare", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CompareUrl failed", e);
                throw new TinEyeServiceException("CompareUrl failed", e);
            }
        }
        /// <summary>
        /// Given one of more metadata queries, get a counter for each query specifying how many
        /// of the collection images match the query. The images counted in the results may
        /// be filtered using json metadata.
        /// </summary>
        /// <remarks>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>count_metadata</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array with a single JSON object which has a metadata field
        ///         set to a list of JSON objects with the counts for each metadata query passed in,
        ///         along with the original metadata passed in
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="countMetadata">Array of metadata queries to get image counts for.</param>
        /// <param name="metadata">Metadata to filter the images counted. Set it to null if 
        /// it is not used.</param>
        /// <returns>The MulticolorEngine API JSON response with the count of images matching
        /// each metadata query passed in.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>count_metadata</c> request or parsing the response.
        /// </exception>
        public JObject CountMetadataCollection(JObject[] countMetadata, JObject metadata)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < countMetadata.Length; i++)
                {
                    messageBuilder.Add("count_metadata[" + i + "]", countMetadata[i].ToString());
                }

                if (metadata != null)
                {
                    messageBuilder.Add("metadata", metadata.ToString());
                }

                return this.PostApiRequest("count_metadata", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CountMetadataCollection failed", e);
                throw new TinEyeServiceException("CountMetadataCollection failed", e);
            }
        }
        /// <summary>
        /// Given one of more colors and metadata queries, get a counter specifying
        /// how many of the collection images with the given colors match each query.
        /// </summary>
        /// <remarks>
        /// <para>A weight may be given for each color indicating how much of a color should 
        /// appear in a matching image. Weights must be given for each color if weights are 
        /// included, and each weight must be between 1 and 100 and they all must add to 100.
        /// </para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>count_metadata</c></description></item>
        ///   <item><term>result</term>
        ///         <description>Array with a single JSON object which has a metadata field
        ///         set to a list of JSON objects with the counts for each image with matching colors,
        ///         for each metadata query passed in.
        ///         </description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// </remarks>
        /// <param name="countMetadata">Array of metadata queries to get image counts for.</param>
        /// <param name="colors">Array of colors in the images to count.</param>
        /// <param name="weights">Array of color weights for each color included the
        /// images to count (optional).</param>
        /// <returns>The MulticolorEngine API JSON response with the count of images matching
        /// the colors and each metadata query passed in.</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>count_metadata</c> request or parsing the response.
        /// </exception>
        public JObject CountMetadataColors(JObject[] countMetadata, Color[] colors, float[] weights)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                for (int i = 0; i < countMetadata.Length; i++)
                {
                    messageBuilder.Add("count_metadata[" + i + "]", countMetadata[i].ToString());
                }

                for (int j = 0; j < colors.Length; j++)
                {
                    // Use RGB format for colors
                    string color = String.Format("{0},{1},{2}", new object[] { colors[j].R, colors[j].G, colors[j].B });
                    messageBuilder.Add("colors[" + j + "]", color);

                    // weights must be the same length as the colors if the weights list is not empty.
                    if (weights.Length > 0)
                    {
                        messageBuilder.Add("weights[" + j + "]", weights[j]);
                    }
                }

                return this.PostApiRequest("count_metadata", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("CountMetadataColors failed", e);
                throw new TinEyeServiceException("CountMetadataColors failed", e);
            }
        }
Пример #19
0
        /// <summary>
        /// Update the metadata for a list of images already present in the hosted image collection.
        /// </summary>
        /// <para>Note there must be one metadata entry for each image filepath passed in.</para>
        /// <para>Returns the MulticolorEngine API JSON response with the following fields:</para>
        /// <list type="table">
        ///   <item><term>status</term>
        ///         <description>One of <c>ok</c>, <c>warn</c> or <c>fail</c></description></item>
        ///   <item><term>method</term>
        ///         <description><c>update_metadata</c></description></item>
        ///   <item><term>result</term>
        ///         <description>empty array</description></item>
        ///   <item><term>error</term>
        ///         <description>Array of error messages if status is not <c>ok</c></description>
        ///   </item>
        /// </list>
        /// <param name="filepaths">Array of hosted image filepaths to update metadata for.</param>
        /// <param name="metadata">The metadata entries to associate with each image filepath.</param>
        /// <returns>The MulticolorEngine API JSON response</returns>
        /// <exception cref="TinEyeServiceException">If an exception occurs issuing the
        /// MulticolorEngine API <c>update_metadata</c> request or parsing the response.
        /// </exception>
        public JObject UpdateMetadata(string[] filepaths, JObject[] metadata)
        {
            HttpMessageBuilder messageBuilder = new HttpMessageBuilder();

            try
            {
                if (filepaths.Length != metadata.Length)
                    throw new TinEyeServiceException("filepaths and metadata list must have the same number of entries.");

                for (int i = 0; i < filepaths.Length; i++)
                {
                    messageBuilder.Add("filepaths[" + i + "]", filepaths[i]);
                    messageBuilder.Add("metadata[" + i + "]", metadata[i].ToString());
                }

                return this.PostApiRequest("update_metadata", messageBuilder.ToArray(), messageBuilder.Boundary);
            }
            catch (Exception e)
            {
                if (log.IsErrorEnabled)
                    log.Error("UpdateMetadata failed", e);
                throw new TinEyeServiceException("UpdateMetadata failed", e);
            }
        }