|
|
@@ -367,9 +367,10 @@ Below are the API references and multi-language service invocation examples:
|
|
|
|
|
|
<details><summary>API Reference</summary>
|
|
|
|
|
|
-<p>For all operations provided by the service:</p>
|
|
|
+<p>For main operations provided by the service:</p>
|
|
|
<ul>
|
|
|
-<li>Both the response body and the request body for POST requests are JSON data (JSON objects).</li>
|
|
|
+<li>The HTTP request method is POST.</li>
|
|
|
+<li>The request body and the response body are both JSON data (JSON objects).</li>
|
|
|
<li>When the request is processed successfully, the response status code is <code>200</code>, and the response body properties are as follows:</li>
|
|
|
</ul>
|
|
|
<table>
|
|
|
@@ -377,32 +378,32 @@ Below are the API references and multi-language service invocation examples:
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
<td><code>errorCode</code></td>
|
|
|
<td><code>integer</code></td>
|
|
|
-<td>Error code. Fixed as <code>0</code>.</td>
|
|
|
+<td>Error code. Fixed to <code>0</code>.</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td><code>errorMsg</code></td>
|
|
|
<td><code>string</code></td>
|
|
|
-<td>Error message. Fixed as <code>"Success"</code>.</td>
|
|
|
+<td>Error description. Fixed to <code>"Success"</code>.</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
-<p>The response body may also have a <code>result</code> property of type <code>object</code>, which stores the operation result information.</p>
|
|
|
+<p>The response body may also have a <code>result</code> property, which is an <code>object</code> type that stores operation result information.</p>
|
|
|
<ul>
|
|
|
-<li>When the request is not processed successfully, the response body properties are as follows:</li>
|
|
|
+<li>When the request is not processed successfully, the properties of the response body are as follows:</li>
|
|
|
</ul>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
@@ -414,58 +415,235 @@ Below are the API references and multi-language service invocation examples:
|
|
|
<tr>
|
|
|
<td><code>errorMsg</code></td>
|
|
|
<td><code>string</code></td>
|
|
|
-<td>Error message.</td>
|
|
|
+<td>Error description.</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
-<p>Operations provided by the service are as follows:</p>
|
|
|
+<p>The main operations provided by the service are as follows:</p>
|
|
|
<ul>
|
|
|
-<li><b><code>infer</code></b></li>
|
|
|
+<li><b><code>buildIndex</code></b></li>
|
|
|
</ul>
|
|
|
-<p>Classify images.</p>
|
|
|
-<p><code>POST /image-classification</code></p>
|
|
|
+<p>Build feature vector index.</p>
|
|
|
+<p><code>POST /shitu-index-build</code></p>
|
|
|
<ul>
|
|
|
-<li>The request body properties are as follows:</li>
|
|
|
+<li>The properties of the request body are as follows:</li>
|
|
|
</ul>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
<th>Required</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
+<td><code>imageLabelPairs</code></td>
|
|
|
+<td><code>array</code></td>
|
|
|
+<td>Image-label pairs for building the index.</td>
|
|
|
+<td>Yes</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<p>Each element in <code>imageLabelPairs</code> is an <code>object</code> with the following properties:</p>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
<td><code>image</code></td>
|
|
|
<td><code>string</code></td>
|
|
|
-<td>The URL of an image file accessible by the service or the Base64 encoded result of the image file content.</td>
|
|
|
+<td>The URL of an image file accessible by the service, or the Base64 encoding result of the image file content.</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>label</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>Label.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<ul>
|
|
|
+<li>When the request is processed successfully, the <code>result</code> of the response body has the following properties:</li>
|
|
|
+</ul>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
+<td><code>indexKey</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The key corresponding to the index, used to identify the established index. Can be used as input for other operations.</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>idMap</code></td>
|
|
|
+<td><code>object</code></td>
|
|
|
+<td>Mapping from vector ID to label.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<ul>
|
|
|
+<li><b><code>addImagesToIndex</code></b></li>
|
|
|
+</ul>
|
|
|
+<p>Add images (corresponding feature vectors) to the index.</p>
|
|
|
+<p><code>POST /shitu-index-add</code></p>
|
|
|
+<ul>
|
|
|
+<li>The properties of the request body are as follows:</li>
|
|
|
+</ul>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+<th>Required</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
+<td><code>imageLabelPairs</code></td>
|
|
|
+<td><code>array</code></td>
|
|
|
+<td>Image-label pairs for building the index.</td>
|
|
|
+<td>Yes</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>indexKey</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The key corresponding to the index. Provided by the <code>buildIndex</code> operation.</td>
|
|
|
<td>Yes</td>
|
|
|
</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<p>Each element in <code>imageLabelPairs</code> is an <code>object</code> with the following properties:</p>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
+<td><code>image</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The URL of an image file accessible by the service, or the Base64 encoding result of the image file content.</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>label</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>Label.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<ul>
|
|
|
+<li>When the request is processed successfully, the <code>result</code> of the response body has the following properties:</li>
|
|
|
+</ul>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
<tr>
|
|
|
-<td><code>inferenceParams</code></td>
|
|
|
+<td><code>idMap</code></td>
|
|
|
<td><code>object</code></td>
|
|
|
-<td>Inference parameters.</td>
|
|
|
-<td>No</td>
|
|
|
+<td>Mapping from vector ID to label.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<ul>
|
|
|
+<li><b><code>removeImagesFromIndex</code></b></li>
|
|
|
+</ul>
|
|
|
+<p>Remove images (corresponding feature vectors) from the index.</p>
|
|
|
+<p><code>POST /shitu-index-remove</code></p>
|
|
|
+<ul>
|
|
|
+<li>The properties of the request body are as follows:</li>
|
|
|
+</ul>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
+<th>Required</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
+<td><code>ids</code></td>
|
|
|
+<td><code>array</code></td>
|
|
|
+<td>IDs of the vectors to be removed from the index.</td>
|
|
|
+<td>Yes</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>indexKey</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The key corresponding to the index. Provided by the <code>buildIndex</code> operation.</td>
|
|
|
+<td>Yes</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
-<p>The properties of <code>inferenceParams</code> are as follows:</p>
|
|
|
+<ul>
|
|
|
+<li>When the request is processed successfully, the <code>result</code> of the response body has the following properties:</li>
|
|
|
+</ul>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
+</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
+<tr>
|
|
|
+<td><code>idMap</code></td>
|
|
|
+<td><code>object</code></td>
|
|
|
+<td>Mapping from vector ID to label.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<ul>
|
|
|
+<li><b><code>infer</code></b></li>
|
|
|
+</ul>
|
|
|
+<p>Perform image recognition.</p>
|
|
|
+<p><code>POST /shitu-infer</code></p>
|
|
|
+<ul>
|
|
|
+<li>The properties of the request body are as follows:</li>
|
|
|
+</ul>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
<th>Required</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
-<td><code>topK</code></td>
|
|
|
-<td><code>integer</code></td>
|
|
|
-<td>Only the top <code>topK</code> categories with the highest scores will be retained in the results.</td>
|
|
|
+<td><code>image</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The URL of an image file accessible by the service, or the Base64 encoding result of the image file content.</td>
|
|
|
+<td>Yes</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>indexKey</code></td>
|
|
|
+<td><code>string</code></td>
|
|
|
+<td>The key corresponding to the index. Provided by the <code>buildIndex</code> operation.</td>
|
|
|
<td>No</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
@@ -478,61 +656,72 @@ Below are the API references and multi-language service invocation examples:
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
-<td><code>categories</code></td>
|
|
|
+<td><code>detectedObjects</code></td>
|
|
|
<td><code>array</code></td>
|
|
|
-<td>Image category information.</td>
|
|
|
+<td>Information of the detected targets.</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td><code>image</code></td>
|
|
|
<td><code>string</code></td>
|
|
|
-<td>The image classification result image. The image is in JPEG format and encoded using Base64.</td>
|
|
|
+<td>Recognition result image. The image is in JPEG format, encoded with Base64.</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
-<p>Each element in <code>categories</code> is an <code>object</code> with the following properties:</p>
|
|
|
+<p>Each element in <code>detectedObjects</code> is an <code>object</code> with the following properties:</p>
|
|
|
<table>
|
|
|
<thead>
|
|
|
<tr>
|
|
|
<th>Name</th>
|
|
|
<th>Type</th>
|
|
|
-<th>Description</th>
|
|
|
+<th>Meaning</th>
|
|
|
</tr>
|
|
|
</thead>
|
|
|
<tbody>
|
|
|
<tr>
|
|
|
-<td><code>id</code></td>
|
|
|
-<td><code>integer</code></td>
|
|
|
-<td>Category ID.</td>
|
|
|
+<td><code>bbox</code></td>
|
|
|
+<td><code>array</code></td>
|
|
|
+<td>Target location. The elements in the array are the x-coordinate of the upper-left corner, the y-coordinate of the upper-left corner, the x-coordinate of the lower-right corner, and the y-coordinate of the lower-right corner, respectively.</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>recResults</code></td>
|
|
|
+<td><code>array</code></td>
|
|
|
+<td>Recognition results.</td>
|
|
|
+</tr>
|
|
|
+<tr>
|
|
|
+<td><code>score</code></td>
|
|
|
+<td><code>number</code></td>
|
|
|
+<td>Detection score.</td>
|
|
|
+</tr>
|
|
|
+</tbody>
|
|
|
+</table>
|
|
|
+<p>Each element in <code>recResults</code> is an <code>object</code> with the following properties:</p>
|
|
|
+<table>
|
|
|
+<thead>
|
|
|
+<tr>
|
|
|
+<th>Name</th>
|
|
|
+<th>Type</th>
|
|
|
+<th>Meaning</th>
|
|
|
</tr>
|
|
|
+</thead>
|
|
|
+<tbody>
|
|
|
<tr>
|
|
|
-<td><code>name</code></td>
|
|
|
+<td><code>label</code></td>
|
|
|
<td><code>string</code></td>
|
|
|
-<td>Category name.</td>
|
|
|
+<td>Label.</td>
|
|
|
</tr>
|
|
|
<tr>
|
|
|
<td><code>score</code></td>
|
|
|
<td><code>number</code></td>
|
|
|
-<td>Category score.</td>
|
|
|
+<td>Recognition score.</td>
|
|
|
</tr>
|
|
|
</tbody>
|
|
|
</table>
|
|
|
-<p>An example of <code>result</code> is as follows:</p>
|
|
|
-<pre><code class="language-json">{
|
|
|
-"categories": [
|
|
|
-{
|
|
|
-"id": 5,
|
|
|
-"name": "Rabbit",
|
|
|
-"score": 0.93
|
|
|
-}
|
|
|
-],
|
|
|
-"image": "xxxxxx"
|
|
|
-}
|
|
|
-</code></pre></details>
|
|
|
+</details>
|
|
|
|
|
|
<details><summary>Multi-Language Service Invocation Examples</summary>
|
|
|
|
|
|
@@ -541,336 +730,82 @@ Below are the API references and multi-language service invocation examples:
|
|
|
|
|
|
|
|
|
<pre><code class="language-python">import base64
|
|
|
+import pprint
|
|
|
+import sys
|
|
|
+
|
|
|
import requests
|
|
|
|
|
|
-API_URL = "http://localhost:8080/image-classification"
|
|
|
-image_path = "./demo.jpg"
|
|
|
+API_BASE_URL = "http://0.0.0.0:8080"
|
|
|
+
|
|
|
+base_image_label_pairs = [
|
|
|
+ {"image": "./demo0.jpg", "label": "兔子"},
|
|
|
+ {"image": "./demo1.jpg", "label": "兔子"},
|
|
|
+ {"image": "./demo2.jpg", "label": "小狗"},
|
|
|
+]
|
|
|
+image_label_pairs_to_add = [
|
|
|
+ {"image": "./demo3.jpg", "label": "小狗"},
|
|
|
+]
|
|
|
+ids_to_remove = [1]
|
|
|
+infer_image_path = "./demo4.jpg"
|
|
|
output_image_path = "./out.jpg"
|
|
|
|
|
|
-with open(image_path, "rb") as file:
|
|
|
+for pair in base_image_label_pairs:
|
|
|
+ with open(pair["image"], "rb") as file:
|
|
|
+ image_bytes = file.read()
|
|
|
+ image_data = base64.b64encode(image_bytes).decode("ascii")
|
|
|
+ pair["image"] = image_data
|
|
|
+
|
|
|
+payload = {"imageLabelPairs": base_image_label_pairs}
|
|
|
+resp_index_build = requests.post(f"{API_BASE_URL}/shitu-index-build", json=payload)
|
|
|
+if resp_index_build.status_code != 200:
|
|
|
+ print(f"Request to shitu-index-build failed with status code {resp_index_build}.")
|
|
|
+ pprint.pp(resp_index_build.json())
|
|
|
+ sys.exit(1)
|
|
|
+result_index_build = resp_index_build.json()["result"]
|
|
|
+print(f"Number of images indexed: {len(result_index_build['idMap'])}")
|
|
|
+
|
|
|
+for pair in image_label_pairs_to_add:
|
|
|
+ with open(pair["image"], "rb") as file:
|
|
|
+ image_bytes = file.read()
|
|
|
+ image_data = base64.b64encode(image_bytes).decode("ascii")
|
|
|
+ pair["image"] = image_data
|
|
|
+
|
|
|
+payload = {"imageLabelPairs": image_label_pairs_to_add, "indexKey": result_index_build["indexKey"]}
|
|
|
+resp_index_add = requests.post(f"{API_BASE_URL}/shitu-index-add", json=payload)
|
|
|
+if resp_index_add.status_code != 200:
|
|
|
+ print(f"Request to shitu-index-add failed with status code {resp_index_add}.")
|
|
|
+ pprint.pp(resp_index_add.json())
|
|
|
+ sys.exit(1)
|
|
|
+result_index_add = resp_index_add.json()["result"]
|
|
|
+print(f"Number of images indexed: {len(result_index_add['idMap'])}")
|
|
|
+
|
|
|
+payload = {"ids": ids_to_remove, "indexKey": result_index_build["indexKey"]}
|
|
|
+resp_index_remove = requests.post(f"{API_BASE_URL}/shitu-index-remove", json=payload)
|
|
|
+if resp_index_remove.status_code != 200:
|
|
|
+ print(f"Request to shitu-index-remove failed with status code {resp_index_remove}.")
|
|
|
+ pprint.pp(resp_index_remove.json())
|
|
|
+ sys.exit(1)
|
|
|
+result_index_remove = resp_index_remove.json()["result"]
|
|
|
+print(f"Number of images indexed: {len(result_index_remove['idMap'])}")
|
|
|
+
|
|
|
+with open(infer_image_path, "rb") as file:
|
|
|
image_bytes = file.read()
|
|
|
image_data = base64.b64encode(image_bytes).decode("ascii")
|
|
|
|
|
|
-payload = {"image": image_data}
|
|
|
-
|
|
|
-response = requests.post(API_URL, json=payload)
|
|
|
+payload = {"image": image_data, "indexKey": result_index_build["indexKey"]}
|
|
|
+resp_infer = requests.post(f"{API_BASE_URL}/shitu-infer", json=payload)
|
|
|
+if resp_infer.status_code != 200:
|
|
|
+ print(f"Request to shitu-infer failed with status code {resp_infer}.")
|
|
|
+ pprint.pp(resp_infer.json())
|
|
|
+ sys.exit(1)
|
|
|
+result_infer = resp_infer.json()["result"]
|
|
|
|
|
|
-assert response.status_code == 200
|
|
|
-result = response.json()["result"]
|
|
|
with open(output_image_path, "wb") as file:
|
|
|
- file.write(base64.b64decode(result["image"]))
|
|
|
+ file.write(base64.b64decode(result_infer["image"]))
|
|
|
print(f"Output image saved at {output_image_path}")
|
|
|
-print("\nCategories:")
|
|
|
-print(result["categories"])
|
|
|
+print("\nDetected objects:")
|
|
|
+pprint.pp(result_infer["detectedObjects"])
|
|
|
</code></pre></details>
|
|
|
-<details><summary>C++</summary>
|
|
|
-
|
|
|
-<pre><code class="language-cpp">#include <iostream>
|
|
|
-#include "cpp-httplib/httplib.h" // https://github.com/Huiyicc/cpp-httplib
|
|
|
-#include "nlohmann/json.hpp" // https://github.com/nlohmann/json
|
|
|
-#include "base64.hpp" // https://github.com/tobiaslocker/base64
|
|
|
-
|
|
|
-int main() {
|
|
|
- httplib::Client client("localhost:8080");
|
|
|
- const std::string imagePath = "./demo.jpg";
|
|
|
- const std::string outputImagePath = "./out.jpg";
|
|
|
-
|
|
|
- httplib::Headers headers = {
|
|
|
- {"Content-Type", "application/json"}
|
|
|
- };
|
|
|
-
|
|
|
- std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
|
|
|
- std::streamsize size = file.tellg();
|
|
|
- file.seekg(0, std::ios::beg);
|
|
|
-
|
|
|
- std::vector<char> buffer(size);
|
|
|
- if (!file.read(buffer.data(), size)) {
|
|
|
- std::cerr << "Error reading file." << std::endl;
|
|
|
- return 1;
|
|
|
- }
|
|
|
- std::string bufferStr(reinterpret_cast<const char*>(buffer.data()), buffer.size());
|
|
|
- std::string encodedImage = base64::to_base64(bufferStr);
|
|
|
-
|
|
|
- nlohmann::json jsonObj;
|
|
|
- jsonObj["image"] = encodedImage;
|
|
|
- std::string body = jsonObj.dump();
|
|
|
-
|
|
|
- auto response = client.Post("/image-classification", headers, body, "application/json");
|
|
|
- if (response && response->status == 200) {
|
|
|
- nlohmann::json jsonResponse = nlohmann::json::parse(response->body);
|
|
|
- auto result = jsonResponse["result"];
|
|
|
-
|
|
|
- encodedImage = result["image"];
|
|
|
- std::string decodedString = base64::from_base64(encodedImage);
|
|
|
- std::vector<unsigned char> decodedImage(decodedString.begin(), decodedString.end());
|
|
|
- std::ofstream outputImage(outPutImagePath, std::ios::binary | std::ios::out);
|
|
|
- if (outputImage.is_open()) {
|
|
|
- outputImage.write(reinterpret_cast<char*>(decodedImage.data()), decodedImage.size());
|
|
|
- outputImage.close();
|
|
|
- std::cout << "Output image saved at " << outPutImagePath << std::endl;
|
|
|
- } else {
|
|
|
- std::cerr << "Unable to open file for writing: " << outPutImagePath << std::endl;
|
|
|
- }
|
|
|
-
|
|
|
- auto categories = result["categories"];
|
|
|
- std::cout << "\nCategories:" << std::endl;
|
|
|
- for (const auto& category : categories) {
|
|
|
- std::cout << category << std::endl;
|
|
|
- }
|
|
|
- } else {
|
|
|
- std::cout << "Failed to send HTTP request." << std::endl;
|
|
|
- return 1;
|
|
|
- }
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-</code></pre></details>
|
|
|
-
|
|
|
-<details><summary>Java</summary>
|
|
|
-
|
|
|
-<pre><code class="language-java">import okhttp3.*;
|
|
|
-import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
-import com.fasterxml.jackson.databind.JsonNode;
|
|
|
-import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
|
-
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.util.Base64;
|
|
|
-
|
|
|
-public class Main {
|
|
|
- public static void main(String[] args) throws IOException {
|
|
|
- String API_URL = "http://localhost:8080/image-classification";
|
|
|
- String imagePath = "./demo.jpg";
|
|
|
- String outputImagePath = "./out.jpg";
|
|
|
-
|
|
|
- File file = new File(imagePath);
|
|
|
- byte[] fileContent = java.nio.file.Files.readAllBytes(file.toPath());
|
|
|
- String imageData = Base64.getEncoder().encodeToString(fileContent);
|
|
|
-
|
|
|
- ObjectMapper objectMapper = new ObjectMapper();
|
|
|
- ObjectNode params = objectMapper.createObjectNode();
|
|
|
- params.put("image", imageData);
|
|
|
-
|
|
|
- OkHttpClient client = new OkHttpClient();
|
|
|
- MediaType JSON = MediaType.Companion.get("application/json; charset=utf-8");
|
|
|
- RequestBody body = RequestBody.Companion.create(params.toString(), JSON);
|
|
|
- Request request = new Request.Builder()
|
|
|
- .url(API_URL)
|
|
|
- .post(body)
|
|
|
- .build();
|
|
|
-
|
|
|
- try (Response response = client.newCall(request).execute()) {
|
|
|
- if (response.isSuccessful()) {
|
|
|
- String responseBody = response.body().string();
|
|
|
- JsonNode resultNode = objectMapper.readTree(responseBody);
|
|
|
- JsonNode result = resultNode.get("result");
|
|
|
- String base64Image = result.get("image").asText();
|
|
|
- JsonNode categories = result.get("categories");
|
|
|
-
|
|
|
- byte[] imageBytes = Base64.getDecoder().decode(base64Image);
|
|
|
- try (FileOutputStream fos = new FileOutputStream(outputImagePath)) {
|
|
|
- fos.write(imageBytes);
|
|
|
- }
|
|
|
- System.out.println("Output image saved at " + outputImagePath);
|
|
|
- System.out.println("\nCategories: " + categories.toString());
|
|
|
- } else {
|
|
|
- System.err.println("Request failed with code: " + response.code());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-</code></pre></details>
|
|
|
-
|
|
|
-<details><summary>Go</summary>
|
|
|
-
|
|
|
-<pre><code class="language-go">package main
|
|
|
-
|
|
|
-import (
|
|
|
- "bytes"
|
|
|
- "encoding/base64"
|
|
|
- "encoding/json"
|
|
|
- "fmt"
|
|
|
- "io/ioutil"
|
|
|
- "net/http"
|
|
|
-)
|
|
|
-
|
|
|
-func main() {
|
|
|
- API_URL := "http://localhost:8080/image-classification"
|
|
|
- imagePath := "./demo.jpg"
|
|
|
- outputImagePath := "./out.jpg"
|
|
|
-
|
|
|
- imageBytes, err := ioutil.ReadFile(imagePath)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error reading image file:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- imageData := base64.StdEncoding.EncodeToString(imageBytes)
|
|
|
-
|
|
|
- payload := map[string]string{"image": imageData}
|
|
|
- payloadBytes, err := json.Marshal(payload)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error marshaling payload:", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- client := &http.Client{}
|
|
|
- req, err := http.NewRequest("POST", API_URL, bytes.NewBuffer(payloadBytes))
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error creating request:", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- res, err := client.Do(req)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error sending request:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- defer res.Body.Close()
|
|
|
-
|
|
|
- body, err := ioutil.ReadAll(res.Body)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error reading response body:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- type Response struct {
|
|
|
- Result struct {
|
|
|
- Image string `json:"image"`
|
|
|
- Categories []map[string]interface{} `json:"categories"`
|
|
|
- } `json:"result"`
|
|
|
- }
|
|
|
- var respData Response
|
|
|
- err = json.Unmarshal([]byte(string(body)), &respData)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error unmarshaling response body:", err)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- outputImageData, err := base64.StdEncoding.DecodeString(respData.Result.Image)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error decoding base64 image data:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- err = ioutil.WriteFile(outputImagePath, outputImageData, 0644)
|
|
|
- if err != nil {
|
|
|
- fmt.Println("Error writing image to file:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- fmt.Printf("Image saved at %s.jpg\n", outputImagePath)
|
|
|
- fmt.Println("\nCategories:")
|
|
|
- for _, category := range respData.Result.Categories {
|
|
|
- fmt.Println(category)
|
|
|
- }
|
|
|
-}
|
|
|
-</code></pre></details>
|
|
|
-
|
|
|
-<details><summary>C#</summary>
|
|
|
-
|
|
|
-<pre><code class="language-csharp">using System;
|
|
|
-using System.IO;
|
|
|
-using System.Net.Http;
|
|
|
-using System.Net.Http.Headers;
|
|
|
-using System.Text;
|
|
|
-using System.Threading.Tasks;
|
|
|
-using Newtonsoft.Json.Linq;
|
|
|
-
|
|
|
-class Program
|
|
|
-{
|
|
|
- static readonly string API_URL = "http://localhost:8080/image-classification";
|
|
|
- static readonly string imagePath = "./demo.jpg";
|
|
|
- static readonly string outputImagePath = "./out.jpg";
|
|
|
-
|
|
|
- static async Task Main(string[] args)
|
|
|
- {
|
|
|
- var httpClient = new HttpClient();
|
|
|
-
|
|
|
- byte[] imageBytes = File.ReadAllBytes(imagePath);
|
|
|
- string image_data = Convert.ToBase64String(imageBytes);
|
|
|
-
|
|
|
- var payload = new JObject{ { "image", image_data } };
|
|
|
- var content = new StringContent(payload.ToString(), Encoding.UTF8, "application/json");
|
|
|
-
|
|
|
- HttpResponseMessage response = await httpClient.PostAsync(API_URL, content);
|
|
|
- response.EnsureSuccessStatusCode();
|
|
|
-
|
|
|
- string responseBody = await response.Content.ReadAsStringAsync();
|
|
|
- JObject jsonResponse = JObject.Parse(responseBody);
|
|
|
-
|
|
|
- string base64Image = jsonResponse["result"]["image"].ToString();
|
|
|
- byte[] outputImageBytes = Convert.FromBase64String(base64Image);
|
|
|
-
|
|
|
- File.WriteAllBytes(outputImagePath, outputImageBytes);
|
|
|
- Console.WriteLine($"Output image saved at {outputImagePath}");
|
|
|
- Console.WriteLine("\nCategories:");
|
|
|
- Console.WriteLine(jsonResponse["result"]["categories"].ToString());
|
|
|
- }
|
|
|
-}
|
|
|
-</code></pre></details>
|
|
|
-
|
|
|
-<details><summary>Node.js</summary>
|
|
|
-
|
|
|
-<pre><code class="language-js">const axios = require('axios');
|
|
|
-const fs = require('fs');
|
|
|
-
|
|
|
-const API_URL = 'http://localhost:8080/image-classification'
|
|
|
-const imagePath = './demo.jpg'
|
|
|
-const outputImagePath = "./out.jpg";
|
|
|
-
|
|
|
-let config = {
|
|
|
- method: 'POST',
|
|
|
- maxBodyLength: Infinity,
|
|
|
- url: API_URL,
|
|
|
- data: JSON.stringify({
|
|
|
- 'image': encodeImageToBase64(imagePath)
|
|
|
- })
|
|
|
-};
|
|
|
-
|
|
|
-function encodeImageToBase64(filePath) {
|
|
|
- const bitmap = fs.readFileSync(filePath);
|
|
|
- return Buffer.from(bitmap).toString('base64');
|
|
|
-}
|
|
|
-
|
|
|
-axios.request(config)
|
|
|
-.then((response) => {
|
|
|
- const result = response.data["result"];
|
|
|
- const imageBuffer = Buffer.from(result["image"], 'base64');
|
|
|
- fs.writeFile(outputImagePath, imageBuffer, (err) => {
|
|
|
- if (err) throw err;
|
|
|
- console.log(`Output image saved at ${outputImagePath}`);
|
|
|
- });
|
|
|
- console.log("\nCategories:");
|
|
|
- console.log(result["categories"]);
|
|
|
-})
|
|
|
-.catch((error) => {
|
|
|
- console.log(error);
|
|
|
-});
|
|
|
-</code></pre></details>
|
|
|
-<details><summary>PHP</summary>
|
|
|
-
|
|
|
-<pre><code class="language-php"><?php
|
|
|
-
|
|
|
-$API_URL = "http://localhost:8080/image-classification";
|
|
|
-$image_path = "./demo.jpg";
|
|
|
-$output_image_path = "./out.jpg";
|
|
|
-
|
|
|
-$image_data = base64_encode(file_get_contents($image_path));
|
|
|
-$payload = array("image" => $image_data);
|
|
|
-
|
|
|
-$ch = curl_init($API_URL);
|
|
|
-curl_setopt($ch, CURLOPT_POST, true);
|
|
|
-curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
|
|
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
|
-$response = curl_exec($ch);
|
|
|
-curl_close($ch);
|
|
|
-
|
|
|
-$result = json_decode($response, true)["result"];
|
|
|
-file_put_contents($output_image_path, base64_decode($result["image"]));
|
|
|
-echo "Output image saved at " . $output_image_path . "\n";
|
|
|
-echo "\nCategories:\n";
|
|
|
-print_r($result["categories"]);
|
|
|
-?>
|
|
|
-</code></pre></details>
|
|
|
-
|
|
|
</details>
|
|
|
<br/>
|
|
|
|