> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/datasets/ko/manage/manage-images.md).

# 이미지 관리

## 정보

Roboflow를 사용하면 REST API와 Python SDK를 통해 프로젝트 내 개별 이미지를 업로드, 주석 추가, 검사, 태그 지정 및 삭제할 수 있습니다. 이러한 작업은 대량 데이터셋 업로드 흐름이 제공하는 것보다 더 세밀한 제어가 필요할 때 사용하세요. 예를 들어 스트림에서 이미지를 한 장씩 업로드하거나, 나중에 주석을 첨부하거나, 이미지 메타데이터와 태그를 업데이트할 때 유용합니다. 레이블이 지정된 전체 데이터셋을 한 번에 대량 가져오려면 다음을 참조하세요 [데이터셋 업로드](/datasets/ko/create-and-upload/upload-a-dataset.md).

## HTTP API

REST API는 이미지 업로드 및 주석 업로드, 이미지 세부 정보 가져오기, 이미지 삭제, 이미지 태그 및 메타데이터 관리를 위한 이미지별 작업을 제공합니다.

### 이미지 업로드

REST API를 사용하여 로컬 파일 또는 URL에서 이미지를 업로드합니다.

다음을 전달할 때 `image=`, Roboflow는 자체 서버에서 URL을 가져옵니다. URL을 가져올 수 없는 경우(잘못된 URL, 사설 주소, 또는 호스트가 4xx 상태로 응답하는 경우) 응답은 "Could not fetch image URL"로 시작하는 메시지와 함께 400입니다. 호스트가 5xx 상태로 응답하거나 연결에 실패하면 응답은 `retryable: true`, 따라서 나중에 동일한 요청을 다시 보낼 수 있습니다.

{% tabs %}
{% tab title="cURL" %}

#### 매개변수

API가 허용하는 쿼리 문자열 매개변수:

**api\_key**: <https://app.roboflow.com/account/api에서> 가져오세요\
**image**: \[선택 사항] 추가할 이미지의 URL입니다. 이미지가 다른 곳에 호스팅된 경우 사용하세요(요청 본문에 base64 인코딩된 이미지를 POST하지 않는 경우 필요).\
**name**: \[선택 사항] 이미지의 파일 이름입니다(설정하지 않으면 추론을 시도합니다).\
**batch**: \[선택 사항] 이 이름으로 이미지를 배치로 묶습니다\
**태그**: \[선택 사항] 여러 번 지정할 수 있습니다. 업로드된 이미지에 태그를 추가합니다.\
**분할**: \[선택 사항] train, valid, test 중 하나입니다(기본값은 train).\
**sequence\_number**: \[선택 사항] 데이터셋에서 이미지 순서를 유지하려면 업로드된 이미지에 증가하는 시퀀스 번호를 지정할 수 있습니다.\
**sequence\_size**: \[선택 사항] 시퀀스 내 총 이미지 수입니다. 설정하지 않으면 기본값은 100,000입니다.\
**inference\_id**: \[선택 사항] roboflow 추론 감지에서 반환되어 전달된 추론 ID입니다. 이 inference\_id를 사용하면 Model Monitoring(엔터프라이즈 기능)에서 이미지를 roboflow 감지와 연관시킬 수 있습니다.

#### Linux 또는 macOS

다음 이름의 로컬 파일을 업로드하는 경우 `YOUR_IMAGE.jpg` multipart/form-data를 사용하여(권장):

```
curl -F name=YOUR_IMAGE.jpg -F split=train \\
-F file=@YOUR_IMAGE.jpg \\
"https://api.roboflow.com/dataset/YOUR_DATASET_NAME/upload?\\
api_key=$ROBOFLOW_API_KEY"
```

대안으로, base64로 인코딩된 이미지를 업로드할 수 있습니다:

```bash
base64 -i YOUR_IMAGE.jpg | curl -d @- \\
"https://api.roboflow.com/dataset/your-dataset/upload?\\
api_key=$ROBOFLOW_API_KEY&\\
name=YOUR_IMAGE.jpg&\\
split=train&\\
batch=BATCH_NAME_FOR_UPLOAD"
```

웹에 호스팅된 이미지를 해당 URL로 업로드할 때(잊지 말고 [URL 인코딩하세요](https://www.urlencoder.org/)):

```bash
curl -X POST "https://api.roboflow.com/dataset/your-dataset/upload?\\
api_key=$ROBOFLOW_API_KEY&\\
image=https%3A%2F%2Fi.imgur.com%2FPEEvqPN.png&\\
name=201-956-1246.png&\\
split=train"
```

#### Windows

설치해야 합니다 [Windows용 curl](https://curl.se/windows/) 와 [Windows용 GNU base64 도구](http://gnuwin32.sourceforge.net/packages/coreutils.htm). 이를 수행하는 가장 쉬운 방법은 [Windows용 git 설치 프로그램을 사용하는 것입니다](https://git-scm.com/downloads) 여기에는 `curl` 와 `base64` 설치 중 "명령 프롬프트에서 Git 및 선택적 Unix 도구 사용"을 선택하면 명령줄 도구도 포함됩니다.

그런 다음 위와 동일한 명령을 사용할 수 있습니다.
{% endtab %}

{% tab title="JavaScript" %}

#### Node.js

다음을 사용합니다 [axios](https://github.com/axios/axios) 와 [form-data](https://github.com/form-data/form-data) 이 예제에서 POST 요청을 수행하기 위해 먼저 `npm install axios form-data` 를 실행하여 의존성을 설치합니다.

#### **multipart/form-data를 사용한 업로드(권장):**

```javascript
const axios = require("axios");
const fs = require("fs");
const FormData = require('form-data');

const formData = new FormData();
formData.append("name", "YOUR_IMAGE.jpg");
formData.append("file", fs.createReadStream("YOUR_IMAGE.jpg"));
formData.append("split", "train");

axios({
    method: "POST",
    url: "https://api.roboflow.com/dataset/YOUR_DATASET_NAME/upload",
    params: {
        api_key: "YOUR_API_KEY"
    },
    data: formData,
    headers: formData.getHeaders()
})
.then(function(response) {
    console.log(response.data);
})
.catch(function(error) {
    console.log(error.message);
});
```

#### **base64로 인코딩된 이미지를 사용한 업로드(권장하지 않음):**

```javascript
const axios = require("axios");
const fs = require("fs");

const image = fs.readFileSync("YOUR_IMAGE.jpg", {
    encoding: "base64"
});

axios({
    method: "POST",
    url: "https://api.roboflow.com/dataset/YOUR_DATASET_NAME/upload",
    params: {
        api_key: "YOUR_API_KEY",
        name: "YOUR_IMAGE.jpg",
        split: "train",
        batch: "YOUR_BATCH_NAME"
    },
    data: image,
    headers: {
        "Content-Type": "application/x-www-form-urlencoded"
    }
})
.then(function(response) {
    console.log(response.data);
})
.catch(function(error) {
    console.log(error.message);
});
```

**다른 곳에 호스팅된 이미지를 URL로 추가**

```javascript
const axios = require("axios");

axios({
    method: "POST",
    url: "https://api.roboflow.com/dataset/YOUR_DATASET_NAME/upload",
    params: {
        api_key: "YOUR_API_KEY",
        image: "https://i.imgur.com/PEEvqPN.png",
        name: "201-956-1246.png",
        split: "train"
    }
})
.then(function(response) {
    console.log(response.data);
})
.catch(function(error) {
    console.log(error.message);
});
```

#### 웹

현재 `roboflow.js`는 브라우저 기반 JavaScript 라이브러리로, 비밀 API 키를 웹에 노출하지 않는 안전한 클라이언트 측 업로드 등을 포함합니다. 조기 액세스를 원하시면 [문의해 주세요](https://roboflow.com/contact).
{% endtab %}

{% tab title="Swift" %}

#### Swift

iOS 개발용 Swift를 사용한 업로드 예제 스니펫입니다.

```swift
// 제공된 프로젝트에 이미지를 업로드
public func uploadImage(image: UIImage, project: String, completion: @escaping (UploadResult)->()) {
    let encodedImage = convertImageToBase64String(img: image)
    let uuid = UUID().uuidString
    
    var request = URLRequest(url: URL(string: "https://api.roboflow.com/dataset/\(project)/upload?api_key=\(apiKey!)&name=\(uuid)&split=train")!,timeoutInterval: Double.infinity)

    request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "POST"
    request.httpBody = encodedImage.toData()
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        // 응답을 문자열로 파싱
        guard let data = data else {
            completion(UploadResult.Error)
            return
        }

        do {
            let dict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            let duplicate = dict!["duplicate"] as? Bool
            
            if duplicate ==  true {
                completion(UploadResult.Duplicate)
            } else {
                let success = dict!["success"] as! Bool
                if success == true {
                    completion(UploadResult.Success)
                } else {
                    completion(UploadResult.Error)
                }
            }

        } catch {
            print(error.localizedDescription)
            completion(UploadResult.Error)
        }
    }.resume()
}

func convertImageToBase64String (img: UIImage) -> String {
    return img.jpegData(compressionQuality: 1)?.base64EncodedString() ?? ""
}
```

}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Android 및 Java" %}

#### Kotlin

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```kotlin
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.*

fun main() {
    // 이미지 경로 가져오기
    val filePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "YOUR_IMAGE.jpg"
    val file = File(filePath)

    // Base 64 인코딩
    val encodedFile: String
    val fileInputStreamReader = FileInputStream(file)
    val bytes = ByteArray(file.length().toInt())
    fileInputStreamReader.read(bytes)
    encodedFile = String(Base64.getEncoder().encode(bytes), StandardCharsets.US_ASCII)
    val API_KEY = "" // API 키
    val DATASET_NAME = "your-dataset" // 데이터셋 이름 설정(데이터셋 URL에서 확인)

    // URL 구성
    val uploadURL = "https://api.roboflow.com/dataset/" +
            DATASET_NAME + "/upload" +
            "?api_key=" + API_KEY +
            "&name=YOUR_IMAGE.jpg" +
            "&split=train"

    // HTTP 요청
    var connection: HttpURLConnection? = null
    try {
        // URL에 대한 연결 구성
        val url = URL(uploadURL)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded")
        connection.setRequestProperty("Content-Length",
                Integer.toString(encodedFile.toByteArray().size))
        connection.setRequestProperty("Content-Language", "en-US")
        connection.useCaches = false
        connection.doOutput = true

        // 요청 전송
        val wr = DataOutputStream(
                connection.outputStream)
        wr.writeBytes(encodedFile)
        wr.close()

        // 응답 가져오기
        val stream = connection.inputStream
        val reader = BufferedReader(InputStreamReader(stream))
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            println(line)
        }
        reader.close()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        connection?.disconnect()
    }
}
main()
```

**URL로 호스팅된 이미지를 추가:**

```kotlin
import java.io.BufferedReader
import java.io.DataOutputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

fun main() {
    val imageURL = "https://i.imgur.com/PEEvqPN.png" // 이미지 URL을 교체
    val API_KEY = "" // API 키
    val DATASET_NAME = "your-dataset" // 데이터셋 이름 설정(데이터셋 URL에서 확인)

    // 업로드 URL
    val uploadURL = ("https://api.roboflow.com/dataset/" + DATASET_NAME + "/upload" + "?api_key=" + API_KEY
            + "&name=YOUR_IMAGE.jpg" + "&split=train" + "&image="
            + URLEncoder.encode(imageURL, "utf-8"))

    // HTTP 요청
    var connection: HttpURLConnection? = null
    try {
        // URL에 대한 연결 구성
        val url = URL(uploadURL)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
        connection.setRequestProperty("Content-Length", Integer.toString(uploadURL.toByteArray().size))
        connection.setRequestProperty("Content-Language", "en-US")
        connection.useCaches = false
        connection.doOutput = true

        // 요청 전송
        val wr = DataOutputStream(connection.outputStream)
        wr.writeBytes(uploadURL)
        wr.close()

        // 응답 가져오기
        val stream = connection.inputStream
        val reader = BufferedReader(InputStreamReader(stream))
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            println(line)
        }
        reader.close()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        connection?.disconnect()
    }
}

main()
```

#### Android(Java)

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class UploadLocal {
    public static void main(String[] args) throws IOException {
        // 이미지 경로 가져오기
        String filePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "YOUR_IMAGE.jpg";
        File file = new File(filePath);

        // Base 64 인코딩
        String encodedFile;
        FileInputStream fileInputStreamReader = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()];
        fileInputStreamReader.read(bytes);
        encodedFile = new String(Base64.getEncoder().encode(bytes), StandardCharsets.US_ASCII);

        String API_KEY = ""; // API 키
        String DATASET_NAME = "your-dataset"; // 데이터셋 이름 설정(데이터셋 URL에서 확인)

        // URL 구성
        String uploadURL =
                "https://api.roboflow.com/dataset/"+
                        DATASET_NAME + "/upload" +
                        "?api_key=" + API_KEY +
                        "&name=YOUR_IMAGE.jpg" +
                        "&split=train";

        // HTTP 요청
        HttpURLConnection connection = null;
        try {
            // URL에 대한 연결 구성
            URL url = new URL(uploadURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");

            connection.setRequestProperty("Content-Length",
                    Integer.toString(encodedFile.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoOutput(true);

            // 요청 전송
            DataOutputStream wr = new DataOutputStream(
                    connection.getOutputStream());
            wr.writeBytes(encodedFile);
            wr.close();

            // 응답 가져오기
            InputStream stream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
```

**URL로 호스팅된 이미지를 추가:**

```java
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class UploadHosted {
    public static void main(String[] args) {
        String imageURL = "https://i.imgur.com/PEEvqPN.png"; // 이미지 URL을 교체
        String API_KEY = ""; // API 키
        String DATASET_NAME = "your-dataset"; // 데이터셋 이름 설정(데이터셋 URL에서 확인)

        // 업로드 URL
        String uploadURL = "https://api.roboflow.com/dataset/" + DATASET_NAME + "/upload" + "?api_key=" + API_KEY
                + "&name=YOUR_IMAGE.jpg" + "&split=train" + "&image="
                + URLEncoder.encode(imageURL, StandardCharsets.UTF_8);

        // HTTP 요청
        HttpURLConnection connection = null;
        try {
            // URL에 대한 연결 구성
            URL url = new URL(uploadURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            connection.setRequestProperty("Content-Length", Integer.toString(uploadURL.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoOutput(true);

            // 요청 전송
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.writeBytes(uploadURL);
            wr.close();

            // 응답 가져오기
            InputStream stream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
```

{% endtab %}

{% tab title="Ruby" %}

#### **Ruby**

{% code title="Gemfile" %}

```ruby
source "https://rubygems.org"

gem "httparty", "~> 0.18.1"
gem "base64", "~> 0.1.0"
gem "cgi", "~> 0.2.1"
```

{% endcode %}

{% code title="Gemfile.lock" %}

```ruby
GEM
  remote: https://rubygems.org/
  specs:
    base64 (0.1.0)
    cgi (0.2.1)
    httparty (0.18.1)
      mime-types (~> 3.0)
      multi_xml (>= 0.5.2)
    mime-types (3.3.1)
      mime-types-data (~> 3.2015)
    mime-types-data (3.2021.0225)
    multi_xml (0.6.0)

PLATFORMS
  x64-mingw32
  x86_64-linux

DEPENDENCIES
  base64 (~> 0.1.0)
  cgi (~> 0.2.1)
  httparty (~> 0.18.1)

BUNDLED WITH
   2.2.15
```

{% endcode %}

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```ruby
require 'base64'
require 'httparty'

encoded = Base64.encode64(File.open("YOUR_IMAGE.jpg", "rb").read)
dataset_name = "your-dataset" # 데이터셋 이름 설정(데이터셋 URL에서 확인)
api_key = "" # 여기에 API KEY

params = "?api_key=" + api_key + 
"&name=YOUR_IMAGE.jpg" + 
"&split=train"

response = HTTParty.post(
    "https://api.roboflow.com/dataset/" + dataset_name + "/upload" + params,
    body: encoded, 
    headers: {
    'Content-Type' => 'application/x-www-form-urlencoded',
    'charset' => 'utf-8'
  })

  puts response

 
```

**URL로 호스팅된 이미지를 추가:**

```ruby
require 'httparty'
require 'cgi'

dataset_name = "your-dataset" # 데이터셋 이름 설정(데이터셋 URL에서 확인)
api_key = "" # 여기에 API KEY
img_url = "https://i.imgur.com/PEEvqPN.png" # URL 구성

img_url = CGI::escape(img_url)

params = "?api_key=" + api_key + 
"&name=YOUR_IMAGE.jpg" + 
"&split=train" +
"&image=" + img_url

response = HTTParty.post(
    "https://api.roboflow.com/dataset/" + dataset_name + "/upload" + params,
    headers: {
    'Content-Type' => 'application/x-www-form-urlencoded',
    'charset' => 'utf-8'
  })

puts response
```

{% endtab %}

{% tab title="PHP" %}

#### **PHP**

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```php
<?php

// 이미지를 Base64로 인코딩
$data = base64_encode(file_get_contents("YOUR_IMAGE.jpg"));

$api_key = ""; // API 키 설정
$dataset_name = "your-dataset"; // 데이터세트 이름 설정 (데이터세트 URL에서 확인)

// Http 요청용 URL
$url = "https://api.roboflow.com/dataset/" 
. $dataset_name .  "/upload" 
.  "?api_key="  .  $api_key  
.  "&name=YOUR_IMAGE.jpg" 
. "&split=train";

// Http 요청 설정 + 전송
$options = array(
  'http' => array (
    'header' => "Content-type: application/x-www-form-urlencoded\r\n",
    'method'  => 'POST',
    'content' => $data
  ));

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
echo $result;
?>
```

**URL로 호스팅된 이미지를 추가:**

```php
<?php

$api_key = ""; // API 키 설정
$dataset_name = "your-dataset"; // 데이터세트 이름 설정 (데이터세트 URL에서 확인)
$img_url = "https://i.imgur.com/PEEvqPN.png";

// Http 요청용 URL
$url = "https://api.roboflow.com/dataset/" 
. $dataset_name .  "/upload" 
.  "?api_key="  .  $api_key  
.  "&name=YOUR_IMAGE.jpg" 
. "&split=train" 
. "&image=" . urlencode($img_url);

// Http 요청 설정 + 전송
$options = array(
  'http' => array (
    'header' => "Content-type: application/x-www-form-urlencoded\r\n",
    'method'  => 'POST'
  ));

$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
echo $result;
?>
```

{% endtab %}

{% tab title="Go" %}

#### **Go**

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```go
package main

import (
    "bufio"
    "encoding/base64"
    "fmt"
    "io/ioutil"
    "os"
	"net/http"
	"strings"
)

func main() {
	api_key := ""  // API 키
	dataset_name := "Your-Dataset" // 데이터세트 이름 설정 (데이터세트 URL에서 확인)

    // 디스크에서 파일 열기.
    f, _ := os.Open("YOUR_IMAGE.jpg")

    // 전체 JPG를 바이트 슬라이스로 읽기.
    reader := bufio.NewReader(f)
    content, _ := ioutil.ReadAll(reader)

    // base64로 인코딩.
    data := base64.StdEncoding.EncodeToString(content)
	uploadURL := "https://api.roboflow.com/dataset/"+ dataset_name + "/upload"+
    "?api_key=" + api_key +
    "&name=YOUR_IMAGE.jpg" +
    "&split=train"

	res, _ := http.Post(uploadURL, "application/x-www-form-urlencoded", strings.NewReader(data))
    body, _ := ioutil.ReadAll(res.Body)
	fmt.Println(string(body))

}
```

**URL로 호스팅된 이미지를 추가:**

```go
package main

import (
    "fmt"
	"net/http"
	"net/url"
	"io/ioutil"

)

func main() {
	api_key := ""  // API 키
	dataset_name := "Your-Dataset" // 데이터세트 이름 설정 (데이터세트 URL에서 확인)
	img_url := "https://i.imgur.com/PEEvqPN.png"


	uploadURL := "https://api.roboflow.com/dataset/"+ dataset_name + "/upload"+
    "?api_key=" + api_key +
    "&name=YOUR_IMAGE.jpg" +
    "&split=train" + "&image=" + url.QueryEscape(img_url)

	res, _ := http.Post(uploadURL, "application/x-www-form-urlencoded", nil)
	body, _ := ioutil.ReadAll(res.Body)
    fmt.Println(string(body))


}
```

{% endtab %}

{% tab title=".NET" %}

#### **.NET**

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```csharp
using System;
using System.IO;
using System.Net;
using System.Text;

namespace UploadLocal
{
    class UploadLocal
    {

        static void Main(string[] args)
        {
            byte[] imageArray = System.IO.File.ReadAllBytes(@"YOUR_IMAGE.jpg");
            string encoded = Convert.ToBase64String(imageArray);
            byte[] data = Encoding.ASCII.GetBytes(encoded);
            string API_KEY = ""; // API 키
            string DATASET_NAME = "your-dataset"; // 데이터세트 이름 설정 (데이터세트 URL에서 확인)

            // URL 구성
            string uploadURL =
                    "https://api.roboflow.com/dataset/" +
                            DATASET_NAME + "/upload" +
                            "?api_key=" + API_KEY +
                            "&name=YOUR_IMAGE.jpg" +
                            "&split=train";

            // 서비스 요청 설정
            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            // 요청 구성
            WebRequest request = WebRequest.Create(uploadURL);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = data.Length;

            // 데이터 쓰기
            using (Stream stream = request.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }

            // 응답 가져오기
            string responseContent = null;
            using (WebResponse response = request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader sr99 = new StreamReader(stream))
                    {
                        responseContent = sr99.ReadToEnd();
                    }
                }
            }

            Console.WriteLine(responseContent);

        }
    }
}
```

**URL로 호스팅된 이미지를 추가:**

```csharp
using System;
using System.IO;
using System.Net;
using System.Web;

namespace UploadHosted
{
    class UploadHosted
    {
        static void Main(string[] args)
        {
            string API_KEY = ""; // API 키
            string DATASET_NAME = "your-dataset"; // 데이터세트 이름 설정 (데이터세트 URL에서 확인)
            string imageURL = "https://i.imgur.com/PEEvqPN.png";
            imageURL = HttpUtility.UrlEncode(imageURL);

            // URL 구성
            string uploadURL =
                    "https://api.roboflow.com/dataset/" +
                            DATASET_NAME + "/upload" +
                            "?api_key=" + API_KEY +
                            "&name=YOUR_IMAGE.jpg" +
                            "&split=train" +
                            "&image=" + imageURL;

            // 서비스 포인트 설정
            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            // Http 요청 구성
            WebRequest request = WebRequest.Create(uploadURL);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ContentLength = 0;

            // 응답 가져오기
            string responseContent = null;
            using (WebResponse response = request.GetResponse())
            {
                using (Stream stream = response.GetResponseStream())
                {
                    using (StreamReader sr99 = new StreamReader(stream))
                    {
                        responseContent = sr99.ReadToEnd();
                    }
                }
            }

            Console.WriteLine(responseContent);

        }
    }
}
```

{% endtab %}
{% endtabs %}

#### Roboflow에서 업로드된 이미지 보기

API를 통해 업로드된 이미지는 `Annotate` 탭의 `unassigned` 열 아래에서 `uploaded via API`.

로 표시됩니다. `batch` upload 매개변수를 지정하면 이미지가 여전히 `Annotate` 탭에서 찾을 수 있지만 `uploaded via API` 배치로 이동하는 대신 지정한 배치에서 찾을 수 있습니다.

### 주석 업로드

이미 기존 주석이 있고 이미지가 함께 있다면, Roboflow에 업로드할 수 있습니다.

{% hint style="success" %}
이는 다음의 [지원되는 주석 형식](http://roboflow.com/formats) 과 함께 작동하며, 업로드된 이미지의 파일 이름을 참조하는 주석 파일을 사용합니다.
{% endhint %}

{% hint style="info" %}
알고 계셨나요? API를 사용하지 않고도 앱의 Upload 페이지에서 이미지와 함께 주석 파일을 드래그 앤 드롭(또는 선택)할 수 있습니다.
{% endhint %}

추가 `prediction=true` 를 사용해 주석을 정답이 아니라 모델 예측으로 저장합니다. 이미지가 아직 업로드 배치에 있고 주석 작업에 들어가지 않았다면, Roboflow가 해당 배치를 Review 작업으로 이동시킵니다.

추가 `predictionRouting=unassigned` 를 사용하면 그 이동을 건너뜁니다. 주석은 여전히 저장되고 이미지는 여전히 주석이 달린 것으로 표시되지만, 해당 배치에 그대로 남아 unassigned 상태로 유지됩니다. 사용 `predictionRouting=review` 를 사용해 기본 라우팅을 요청합니다. 두 값 모두 `prediction=true`가 필요하며, `jobName`.

{% tabs %}
{% tab title="cURL" %}

#### 예시

다음에 [VOC XML 주석](https://roboflow.com/formats/pascal-voc-xml) 을 ID가 `abc123` 인 이미지에 연결하기 `your-dataset` 데이터세트에서 `YOUR_ANNOTATION.xml`:

```bash
cat YOUR_ANNOTATION.xml | curl -d @- \\\
"https://api.roboflow.com/dataset/your-dataset/annotate/abc123?\
api_key=YOUR_KEY&\
name=YOUR_ANNOTATION.xml"
```

다음에 [Darknet TXT 주석](https://roboflow.com/formats/yolo-darknet-txt) 을 ID가 `abc123` 인 이미지에 연결하기 `your-dataset` 데이터세트에서 `YOUR_ANNOTATION.txt` json labelmap을 사용하는 경우 - 이 경우 주석 파일의 내용을 본문으로 보내는 대신 json으로 보내야 합니다.

```bash
#!/bin/bash
# 주석을 json 호환 문자열로 저장
txt_content=$(cat YOUR_ANNOTATION.txt | sed 's/\\/\\\\/g; s/"/\\"/g; s/$/\\n/' | tr -d '\n')
# 주석 파일과 label map [0=flower, 1=leaf]을 포함한 json 문자열 생성
json_payload="{ \"annotationFile\": \"$txt_content\", \"labelmap\":{\"0\":\"flower\", \"1\":\"leaf\"} }"

# 주석 + labelmap 업로드
echo $json_payload | curl -H "Content-Type: application/json" -d @- \\\
"https://api.roboflow.com/dataset/cultura-pepino-dark/annotate/abc123?\
api_key=YOUR_KEY&\
name=YOUR_ANNOTATION.txt"
```

{% endtab %}

{% tab title="JavaScript" %}
다음을 사용합니다 [axios](https://github.com/axios/axios) 이 예제에서 POST 요청을 수행하기 위해 먼저 `npm install axios` 를 실행하여 의존성을 설치합니다.

**로컬 이미지 업로드**

```javascript
const axios = require("axios");
const fs = require("fs");

const filename = "YOUR_ANNOTATION.xml";
const annotation = fs.readFileSync(filename, "utf-8");

axios({
    method: "POST",
    url: "https://api.roboflow.com/dataset/your-dataset/annotate/abc123",
    params: {
        api_key: "YOUR_KEY",
        name: filename
    },
    data: annotation,
    headers: {
        "Content-Type": "text/plain"
    }
})
.then(function(response) {
    console.log(response.data);
})
.catch(function(error) {
    console.log(error.message);
});
```

{% endtab %}

{% tab title="Android 및 Java" %}

#### Kotlin

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```kotlin
import java.io.*
import java.net.HttpURLConnection
import java.net.URL
import java.nio.charset.StandardCharsets
import java.util.*

fun main() {
    // 이미지 경로 가져오기
    val filePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "YOUR_IMAGE.jpg"
    val file = File(filePath)

    // Base 64 인코딩
    val encodedFile: String
    val fileInputStreamReader = FileInputStream(file)
    val bytes = ByteArray(file.length().toInt())
    fileInputStreamReader.read(bytes)
    encodedFile = String(Base64.getEncoder().encode(bytes), StandardCharsets.US_ASCII)
    val API_KEY = "" // API 키
    val DATASET_NAME = "your-dataset" // 데이터셋 이름 설정(데이터셋 URL에서 확인)

    // URL 구성
    val uploadURL = "https://api.roboflow.com/dataset/" +
            DATASET_NAME + "/upload" +
            "?api_key=" + API_KEY +
            "&name=YOUR_IMAGE.jpg" +
            "&split=train"

    // HTTP 요청
    var connection: HttpURLConnection? = null
    try {
        // URL에 대한 연결 구성
        val url = URL(uploadURL)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Content-Type",
                "application/x-www-form-urlencoded")
        connection.setRequestProperty("Content-Length",
                Integer.toString(encodedFile.toByteArray().size))
        connection.setRequestProperty("Content-Language", "en-US")
        connection.useCaches = false
        connection.doOutput = true

        // 요청 전송
        val wr = DataOutputStream(
                connection.outputStream)
        wr.writeBytes(encodedFile)
        wr.close()

        // 응답 가져오기
        val stream = connection.inputStream
        val reader = BufferedReader(InputStreamReader(stream))
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            println(line)
        }
        reader.close()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        connection?.disconnect()
    }
}
main()
```

**URL로 호스팅된 이미지를 추가:**

```kotlin
import java.io.BufferedReader
import java.io.DataOutputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.net.URLEncoder
import java.nio.charset.StandardCharsets

fun main() {
    val imageURL = "https://i.imgur.com/PEEvqPN.png" // 이미지 URL을 교체
    val API_KEY = "" // API 키
    val DATASET_NAME = "your-dataset" // 데이터셋 이름 설정(데이터셋 URL에서 확인)

    // 업로드 URL
    val uploadURL = ("https://api.roboflow.com/dataset/" + DATASET_NAME + "/upload" + "?api_key=" + API_KEY
            + "&name=YOUR_IMAGE.jpg" + "&split=train" + "&image="
            + URLEncoder.encode(imageURL, "utf-8"))

    // HTTP 요청
    var connection: HttpURLConnection? = null
    try {
        // URL에 대한 연결 구성
        val url = URL(uploadURL)
        connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
        connection.setRequestProperty("Content-Length", Integer.toString(uploadURL.toByteArray().size))
        connection.setRequestProperty("Content-Language", "en-US")
        connection.useCaches = false
        connection.doOutput = true

        // 요청 전송
        val wr = DataOutputStream(connection.outputStream)
        wr.writeBytes(uploadURL)
        wr.close()

        // 응답 가져오기
        val stream = connection.inputStream
        val reader = BufferedReader(InputStreamReader(stream))
        var line: String?
        while (reader.readLine().also { line = it } != null) {
            println(line)
        }
        reader.close()
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        connection?.disconnect()
    }
}

main()
```

#### Android(Java)

#### **base64로 인코딩된 이미지를 사용한 업로드:**

```java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class UploadLocal {
    public static void main(String[] args) throws IOException {
        // 이미지 경로 가져오기
        String filePath = System.getProperty("user.dir") + System.getProperty("file.separator") + "YOUR_IMAGE.jpg";
        File file = new File(filePath);

        // Base 64 인코딩
        String encodedFile;
        FileInputStream fileInputStreamReader = new FileInputStream(file);
        byte[] bytes = new byte[(int) file.length()];
        fileInputStreamReader.read(bytes);
        encodedFile = new String(Base64.getEncoder().encode(bytes), StandardCharsets.US_ASCII);

        String API_KEY = ""; // API 키
        String DATASET_NAME = "your-dataset"; // 데이터셋 이름 설정(데이터셋 URL에서 확인)

        // URL 구성
        String uploadURL =
                "https://api.roboflow.com/dataset/"+
                        DATASET_NAME + "/upload" +
                        "?api_key=" + API_KEY +
                        "&name=YOUR_IMAGE.jpg" +
                        "&split=train";

        // HTTP 요청
        HttpURLConnection connection = null;
        try {
            // URL에 대한 연결 구성
            URL url = new URL(uploadURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded");

            connection.setRequestProperty("Content-Length",
                    Integer.toString(encodedFile.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoOutput(true);

            // 요청 전송
            DataOutputStream wr = new DataOutputStream(
                    connection.getOutputStream());
            wr.writeBytes(encodedFile);
            wr.close();

            // 응답 가져오기
            InputStream stream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
```

**URL로 호스팅된 이미지를 추가:**

```java
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class UploadHosted {
    public static void main(String[] args) {
        String imageURL = "https://i.imgur.com/PEEvqPN.png"; // 이미지 URL을 교체
        String API_KEY = ""; // API 키
        String DATASET_NAME = "your-dataset"; // 데이터셋 이름 설정(데이터셋 URL에서 확인)

        // 업로드 URL
        String uploadURL = "https://api.roboflow.com/dataset/" + DATASET_NAME + "/upload" + "?api_key=" + API_KEY
                + "&name=YOUR_IMAGE.jpg" + "&split=train" + "&image="
                + URLEncoder.encode(imageURL, StandardCharsets.UTF_8);

        // HTTP 요청
        HttpURLConnection connection = null;
        try {
            // URL에 대한 연결 구성
            URL url = new URL(uploadURL);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            connection.setRequestProperty("Content-Length", Integer.toString(uploadURL.getBytes().length));
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setUseCaches(false);
            connection.setDoOutput(true);

            // 요청 전송
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.writeBytes(uploadURL);
            wr.close();

            // 응답 가져오기
            InputStream stream = connection.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
```

{% endtab %}
{% endtabs %}

### 이미지에 대한 세부 정보 가져오기

REST API를 사용하여 특정 이미지의 세부 정보를 가져올 수 있습니다.

특정 이미지의 세부 정보를 가져오려면 다음 API 엔드포인트에 GET 요청을 보내세요.

```url
https://api.roboflow.com/:workspace/:project/images/:image_id
```

이미지의 세부 정보를 가져오기 위한 API 요청 예시는 다음과 같습니다.

```bash
curl -X GET "https://api.roboflow.com/my-workspace/my-project-name/images/image-id?api_key=$ROBOFLOW_API_KEY" \\\
-H 'Content-Type: application/json'
```

이 엔드포인트는 이미지에 대한 다음 정보를 포함한 JSON 객체를 반환합니다:

```typescript
{
    "image":
        "id": string,
        "name": string,
        "annotation": {
            "key": string,
            "width": number,
            "height": number,
            "boxes": Array<{
                "label": string,
                "x": number,
                "y": number,
                "width": number,
                "height": number
            }>
        },
        "labels": string[],
        "split": string,
        "tags": string[],
        "created": number,
        "urls": {
            "original": string,
            "thumb": string,
            "annotation": string
        },
        "embedding": number[]
    }
}
```

### 데이터세트에서 이미지 삭제

REST API를 사용하여 데이터세트에서 이미지를 제거할 수 있습니다.

{% tabs %}
{% tab title="REST API" %}
데이터세트에서 이미지를 제거하려면 다음 API 엔드포인트에 DELETE 요청을 보내고, 엔드포인트에 이미지 ID를 전달하세요.

```url
https://api.roboflow.com/:workspace/:project/images
```

이미지를 제거하기 위한 API 요청 예시는 다음과 같습니다.

```bash
curl "https://api.roboflow.com/my-workspace/my-project/images?api_key=$ROBOFLOW_API_KEY" \\\
  -X DELETE \\\
  -H "Content-Type: application/json" \\
  -d '{"images": ["1", "2"]}'
```

작업이 성공하면 이 엔드포인트는 204 상태를 반환합니다.
{% endtab %}
{% endtabs %}

### 이미지 태그 목록, 추가, 제거

REST API를 사용하여 Roboflow의 특정 이미지에 태그를 지정할 수 있습니다

{% tabs %}
{% tab title="REST API" %}
Roboflow에서 호스팅되는 이미지에 태그를 추가, 제거, 설정하려면 다음 API 엔드포인트에 POST 요청을 보내세요. Search API를 사용해 이미지 이름과 연결된 이미지 ID를 가져오세요:

```url
https://api.roboflow.com/:workspace/:project/images/:image_id/tags
```

API 요청 예시는 다음과 같습니다(태그를 "add", "remove", "set" 할 수 있습니다):

```bash
curl -X POST "https://api.roboflow.com/my-workspace/my-project-name/images/image-id/tags?api_key=$ROBOFLOW_API_KEY" \\\
-H 'Content-Type: application/json' \
--data \
'{
    "operation": "add",
    "tags": "image_tag_test"
}'
```

이 엔드포인트는 POST 본문에서 다음 값을 허용합니다:

```json
{
     // // 옵션은 ["add", "remove", "set"]입니다
     "operation": string,
     
     // 태그 문자열 배열
     "tags": string[],
     
}
```

API는 Roboflow의 지정된 이미지에 태그를 추가합니다(POST 요청에는 이미지 이름이 아니라 이미지 ID를 전달해야 한다는 점을 기억하세요).
{% endtab %}
{% endtabs %}

### 이미지 메타데이터 및 태그 업데이트

REST API를 사용하여 작업 공간의 이미지에 사용자 지정 메타데이터와 태그를 작성할 수 있습니다. 엔드포인트는 두 개가 있습니다: 하나는 단일 이미지를 동기적으로 업데이트하는 용도이고, 다른 하나는 한 번에 최대 1,000개의 이미지를 배치로 업데이트하는 용도입니다.

두 엔드포인트 모두 다음 권한의 API 키가 필요합니다. `image:tag` 권한 범위.

#### 요청 본문

두 엔드포인트는 동일한 필드를 받습니다(배치 엔드포인트는 이를 `updates` 배열로 감쌉니다):

```
- imageId (string) - 본문의 배치 업데이트에 필요하며, 단일 업데이트에서는 경로에서 추론됩니다
- metadata (object) - 이미지의 사용자 메타데이터에 설정할 키-값 쌍.
- removeMetadata (string[]) - 이미지에서 삭제할 메타데이터 키.
- addTags (string[]) - 이미지에 추가할 태그.
- removeTags (string[]) - 이미지에서 제거할 태그.
```

이러한 필드 중 최소 하나는 포함해야 합니다. 같은 요청에서 같은 메타데이터 키나 태그를 설정하고 제거할 수는 없습니다. 다음으로 시작하는 메타데이터 키는 `_rf_internal_` 는 Roboflow용으로 예약되어 있으며 거부됩니다.

#### 단일 이미지

단일 이미지의 메타데이터와 태그를 업데이트합니다.

```
POST https://api.roboflow.com/:workspace/images/:image/metadata?api_key=YOUR_API_KEY
```

**예시**

```bash
curl -X POST "https://api.roboflow.com/my-workspace/images/abc123/metadata?api_key=$ROBOFLOW_API_KEY" \\\
  -H "Content-Type: application/json" \\
  -d '{
    "metadata": { "camera": "front", "blur_score": 0.8 },
    "addTags": ["reviewed"]
  }'
```

**응답**

```json
{
    "success": true
}
```

#### 배치 업데이트

여러 이미지의 메타데이터와 태그를 비동기적으로 업데이트합니다. 요청당 최대 1,000개의 이미지를 지원합니다.

```
POST https://api.roboflow.com/:workspace/images/metadata?api_key=YOUR_API_KEY
```

**예시**

```bash
curl -X POST "https://api.roboflow.com/my-workspace/images/metadata?api_key=$ROBOFLOW_API_KEY" \\\
  -H "Content-Type: application/json" \\
  -d '{
    "updates": [
      {
        "imageId": "abc123",
        "metadata": { "camera": "front" },
        "addTags": ["reviewed"]
      },
      {
        "imageId": "def456",
        "removeTags": ["needs-review"]
      }
    ]
  }'
```

**응답**

반환 `202` 작업 ID와 함께 반환됩니다. 진행 상황을 확인하려면 작업 URL을 폴링하세요.

```json
{
    "taskId": "task-id-here",
    "url": "https://api.roboflow.com/my-workspace/asynctasks/task-id-here"
}
```

참조 [비동기 작업](https://docs.roboflow.com/reference/platform/rest-api/async-tasks) 작업 상태를 폴링하는 방법은 다음과 같습니다.

#### 오류

```
- 400 - 본문이 비어 있거나, 필드 유형이 잘못되었거나, 필드가 충돌하는 경우(예: metadata와 removeMetadata에 같은 키가 있는 경우).
- 404 - 작업 공간에서 이미지를 찾을 수 없음(단일 이미지 엔드포인트만 해당).
```

## Python SDK

`프로젝트` 대량 [`upload_dataset`](/datasets/ko/create-and-upload/upload-a-dataset.md#python-sdk) 흐름을 보완하는 이미지별 작업을 제공합니다. 더 세밀한 단일 이미지 업로드 제어가 필요하거나, 나중에 주석을 첨부하려 하거나, 스트림에서 이미지를 하나씩 수집하는 경우에 사용하세요.

### 이미지 업로드(선택적 주석 포함)

`Project.upload()` 는 상위 수준의 "알아서 잘 처리하는" 도우미입니다. 단일 이미지와 선택적 일치 주석 파일을 받아 한 번의 호출로 둘 다 프로젝트에 전송합니다.

```python
import roboflow

rf = roboflow.Roboflow(api_key="YOUR_API_KEY")
project = rf.workspace().project("my-detector")

result = project.upload(
    image_path="./photo.jpg",
    annotation_path="./photo.xml",   # 선택 사항; 일치하는 VOC / COCO / etc. 주석
    split="train",                    # train | valid | test
    batch_name="ingest-2026-05",     # 선택 사항; 웹 UI에서 업로드를 그룹화
    tag_names=["camera-A", "indoor"], # 선택 사항; 태그 적용
    is_prediction=False,              # 검토를 기다리는 모델 생성 주석의 경우 True로 설정
    num_retry_uploads=2,              # 일시적 업로드 실패 시 재시도
)
print(result)
```

`single_upload()` 는 동일한 인수를 받고 이미지와 (제공된 경우) 주석에 대한 원시 API 응답을 반환하는 하위 수준 변형입니다.

### 이미지만 업로드

```python
project.upload_image(
    image_path="./photo.jpg",
    split="train",
    batch_name="ingest-2026-05",
    tag_names=["camera-A"],
)
```

주석이 아직 없고 이미지가 바로 라벨러로 전달될 때 유용합니다.

### 업로드 전에 이미지 검증

`check_valid_image()` API를 호출하지 않고 Roboflow의 로컬 크기 / 형식 검사를 실행합니다:

```python
if project.check_valid_image("./photo.jpg"):

    project.upload_image("./photo.jpg")
```

### 기존 이미지에 주석 첨부

`save_annotation()` 이미 프로젝트에 있는 이미지에 주석을 게시합니다. 다른 곳에서 만든 레이블을 추가하거나, 모델 예측을 정답으로 승격할 때 유용합니다.

```python
project.save_annotation(
    image_id="<image-id>",
    annotation_path="./photo.xml",
    is_prediction=False,
    annotation_overwrite=True,    # 기존 주석을 대체
)
```

전달 `annotation_labelmap="./labelmap.yaml"` 주석 형식이 요구하는 경우 클래스 인덱스를 클래스 이름으로 매핑합니다.

다음과 함께 저장하면 `is_prediction=True` 이미지를 검토 작업으로 이동시킬 수 있습니다. 다음을 참조하세요. [예측이 저장되는 위치](/datasets/ko/create-and-upload/upload-a-dataset.md#where-predictions-land).

### 이미지의 메타데이터 가져오기

```python
info = project.image("<image-id>")
print(info["name"], info["split"], info["annotations"])
```

이미지 메타데이터, 현재 분할, 주석 상태를 반환합니다.

### 이미지 삭제

프로젝트 수준(이 프로젝트에 속한 이미지만 삭제):

```python
project.delete_images(["<image-id-1>", "<image-id-2>"])
```

워크스페이스 수준(어떤 프로젝트가 참조하든 상관없이 이미지를 제거합니다 - 주의해서 사용하세요):

```python
workspace.delete_images(["<image-id-1>", "<image-id-2>"])
```

### v1.3.6+의 업로드에 대한 참고 사항

현재 `roboflow` 1.3.6부터 SDK는 Pillow를 통해 다시 인코딩하는 대신 원본 이미지 바이트를 업로드합니다. 이는 웹 업로더와의 동등성을 복원하고 Roboflow 서버가 SHA-256으로 업로드를 중복 제거할 수 있게 합니다. 동일한 이미지를 두 번 업로드하는 자동화가 있다면(예: 여러 배치에 추가하기 위해), 두 번째 업로드는 추가 저장 공간 크레딧을 소모하지 않고 성공하는 것을 볼 수 있습니다.

## CLI

CLI를 사용해 이미지 한 장과 선택적 주석, 태그 또는 메타데이터를 업로드합니다.

```bash
roboflow image upload photo.jpg -p PROJECT_ID
```

### 옵션

<table data-search="false"><thead><tr><th>플래그</th><th>설명</th></tr></thead><tbody><tr><td><code>-p</code>, <code>--project</code></td><td>프로젝트 ID (필수)</td></tr><tr><td><code>-a</code>, <code>--annotation</code></td><td>주석 파일 경로</td></tr><tr><td><code>-m</code>, <code>--labelmap</code></td><td>레이블 맵 파일 경로</td></tr><tr><td><code>-s</code>, <code>--split</code></td><td>데이터셋 분할: <code>학습</code>, <code>검증</code>, 또는 <code>테스트</code>. 기본값은 <code>학습</code>.</td></tr><tr><td><code>-t</code>, <code>--tag</code></td><td>쉼표로 구분된 태그 이름</td></tr><tr><td><code>-M</code>, <code>--metadata</code></td><td>JSON 문자열로 된 메타데이터</td></tr><tr><td><code>--is-prediction</code></td><td>업로드를 예측으로 표시합니다</td></tr><tr><td><code>-b</code>, <code>--batch</code></td><td>배치 이름</td></tr></tbody></table>

### 예시

주석이 포함된 이미지를 업로드합니다:

```bash
roboflow image upload photo.jpg -p my-project -a annotation.xml -s valid
```

태그와 메타데이터가 포함된 이미지를 업로드합니다:

```bash
roboflow image upload photo.jpg -p my-project -t "outdoor,daytime" -M '{"camera_id":"cam001"}'
```

디렉터리 또는 `.zip` 압축 파일을 업로드하려면, 다음을 참조하세요 [데이터셋 업로드](/datasets/ko/create-and-upload/upload-a-dataset.md).

## MCP 서버

AI 에이전트를 [MCP 서버](https://docs.roboflow.com/agents/mcp-server) 그리고 다음 도구를 사용해 이미지를 찾고 업데이트할 수 있습니다:

<table data-search="false"><thead><tr><th width="290">도구</th><th>설명</th></tr></thead><tbody><tr><td><code>images_search</code></td><td>프로젝트 내부에서 이미지를 검색합니다.</td></tr><tr><td><code>images_update_metadata</code></td><td>단일 이미지의 메타데이터와 태그를 업데이트합니다.</td></tr><tr><td><code>images_batch_update_metadata</code></td><td>여러 이미지의 메타데이터와 태그를 일괄 업데이트합니다.</td></tr><tr><td><code>annotations_save</code></td><td>기존 이미지의 주석을 저장합니다.</td></tr></tbody></table>
