image-api-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- image_api_sdk-0.1.0/LICENSE +21 -0
- image_api_sdk-0.1.0/PKG-INFO +89 -0
- image_api_sdk-0.1.0/README.md +75 -0
- image_api_sdk-0.1.0/image_api_sdk/__init__.py +10 -0
- image_api_sdk-0.1.0/image_api_sdk/client.py +182 -0
- image_api_sdk-0.1.0/image_api_sdk/result.py +126 -0
- image_api_sdk-0.1.0/image_api_sdk.egg-info/PKG-INFO +89 -0
- image_api_sdk-0.1.0/image_api_sdk.egg-info/SOURCES.txt +11 -0
- image_api_sdk-0.1.0/image_api_sdk.egg-info/dependency_links.txt +1 -0
- image_api_sdk-0.1.0/image_api_sdk.egg-info/requires.txt +3 -0
- image_api_sdk-0.1.0/image_api_sdk.egg-info/top_level.txt +1 -0
- image_api_sdk-0.1.0/pyproject.toml +22 -0
- image_api_sdk-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 seje06
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: image-api-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for a C++ image processing API server
|
|
5
|
+
Author: seje06
|
|
6
|
+
License: LICENSE
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: requests>=2.31.0
|
|
11
|
+
Requires-Dist: pillow>=10.0.0
|
|
12
|
+
Requires-Dist: numpy>=1.24.0
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# cv_api_python_sdk
|
|
16
|
+
이미지 처리를 해주는 cv api 서버를 활용하기 위한 파이썬 라이브러리 개발
|
|
17
|
+
|
|
18
|
+
## 세팅
|
|
19
|
+
|
|
20
|
+
1. 가상환경
|
|
21
|
+
```bash
|
|
22
|
+
> python -m venv .venv
|
|
23
|
+
> .venv\Scripts\activate
|
|
24
|
+
```
|
|
25
|
+
2. 필요 라이브러리 설치
|
|
26
|
+
```bash
|
|
27
|
+
> pip install requests pillow numpy
|
|
28
|
+
> pip freeze > requirements.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 라이브러리화
|
|
32
|
+
|
|
33
|
+
- 구조
|
|
34
|
+
```text
|
|
35
|
+
cv_api_python_sdk/
|
|
36
|
+
├─ image_api_sdk/
|
|
37
|
+
│ ├─ __init__.py
|
|
38
|
+
│ ├─ client.py
|
|
39
|
+
│ └─ result.py
|
|
40
|
+
├─ examples/
|
|
41
|
+
│ └─ basic_example.py
|
|
42
|
+
├─ README.md
|
|
43
|
+
├─ LICENSE
|
|
44
|
+
├─ pyproject.toml
|
|
45
|
+
└─ requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### 필요 파일 작성
|
|
50
|
+
|
|
51
|
+
- pyproject.toml - [작성파일](pyproject.toml)
|
|
52
|
+
- 프로젝트의 모든 설정과 배포 명세서를 담은 표준 지도
|
|
53
|
+
|
|
54
|
+
- LICENSE - [작성파일](LICENSE)
|
|
55
|
+
- 프로젝트를 사용하는 사람들에게 주는 허가증(권리 증명서) 역할
|
|
56
|
+
|
|
57
|
+
### 필요 라이브러리 설치 및 실행
|
|
58
|
+
|
|
59
|
+
1. 배포파일 생성
|
|
60
|
+
```bash
|
|
61
|
+
pip install build
|
|
62
|
+
python -m build
|
|
63
|
+
```
|
|
64
|
+
2. 다른 가상환경에서 테스트
|
|
65
|
+
- bash
|
|
66
|
+
``` bash
|
|
67
|
+
pip install (프로젝트의 부모절대경로)\cv_api_python_sdk\dist\image_api_sdk-0.1.0-py3-none-any.whl
|
|
68
|
+
```
|
|
69
|
+
- python
|
|
70
|
+
```python
|
|
71
|
+
from image_api_sdk import ImageApiClient
|
|
72
|
+
print("import success")
|
|
73
|
+
```
|
|
74
|
+
3. PYPI(공용파이썬 라이브러리 저장소) 에 올리기
|
|
75
|
+
- twine 설치
|
|
76
|
+
```bash
|
|
77
|
+
pip install twine
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## 예시 사용법
|
|
82
|
+
|
|
83
|
+
- 설치
|
|
84
|
+
```bash
|
|
85
|
+
pip install image-api-sdk
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- [예시코드](./examples/basic_example.py)
|
|
89
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# cv_api_python_sdk
|
|
2
|
+
이미지 처리를 해주는 cv api 서버를 활용하기 위한 파이썬 라이브러리 개발
|
|
3
|
+
|
|
4
|
+
## 세팅
|
|
5
|
+
|
|
6
|
+
1. 가상환경
|
|
7
|
+
```bash
|
|
8
|
+
> python -m venv .venv
|
|
9
|
+
> .venv\Scripts\activate
|
|
10
|
+
```
|
|
11
|
+
2. 필요 라이브러리 설치
|
|
12
|
+
```bash
|
|
13
|
+
> pip install requests pillow numpy
|
|
14
|
+
> pip freeze > requirements.txt
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 라이브러리화
|
|
18
|
+
|
|
19
|
+
- 구조
|
|
20
|
+
```text
|
|
21
|
+
cv_api_python_sdk/
|
|
22
|
+
├─ image_api_sdk/
|
|
23
|
+
│ ├─ __init__.py
|
|
24
|
+
│ ├─ client.py
|
|
25
|
+
│ └─ result.py
|
|
26
|
+
├─ examples/
|
|
27
|
+
│ └─ basic_example.py
|
|
28
|
+
├─ README.md
|
|
29
|
+
├─ LICENSE
|
|
30
|
+
├─ pyproject.toml
|
|
31
|
+
└─ requirements.txt
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
### 필요 파일 작성
|
|
36
|
+
|
|
37
|
+
- pyproject.toml - [작성파일](pyproject.toml)
|
|
38
|
+
- 프로젝트의 모든 설정과 배포 명세서를 담은 표준 지도
|
|
39
|
+
|
|
40
|
+
- LICENSE - [작성파일](LICENSE)
|
|
41
|
+
- 프로젝트를 사용하는 사람들에게 주는 허가증(권리 증명서) 역할
|
|
42
|
+
|
|
43
|
+
### 필요 라이브러리 설치 및 실행
|
|
44
|
+
|
|
45
|
+
1. 배포파일 생성
|
|
46
|
+
```bash
|
|
47
|
+
pip install build
|
|
48
|
+
python -m build
|
|
49
|
+
```
|
|
50
|
+
2. 다른 가상환경에서 테스트
|
|
51
|
+
- bash
|
|
52
|
+
``` bash
|
|
53
|
+
pip install (프로젝트의 부모절대경로)\cv_api_python_sdk\dist\image_api_sdk-0.1.0-py3-none-any.whl
|
|
54
|
+
```
|
|
55
|
+
- python
|
|
56
|
+
```python
|
|
57
|
+
from image_api_sdk import ImageApiClient
|
|
58
|
+
print("import success")
|
|
59
|
+
```
|
|
60
|
+
3. PYPI(공용파이썬 라이브러리 저장소) 에 올리기
|
|
61
|
+
- twine 설치
|
|
62
|
+
```bash
|
|
63
|
+
pip install twine
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## 예시 사용법
|
|
68
|
+
|
|
69
|
+
- 설치
|
|
70
|
+
```bash
|
|
71
|
+
pip install image-api-sdk
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
- [예시코드](./examples/basic_example.py)
|
|
75
|
+
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# client.py에서 핵심 클라이언트 클래스와 에러 클래스를 가져온다.
|
|
2
|
+
from .client import ImageApiClient, ImageApiError
|
|
3
|
+
|
|
4
|
+
# result.py에서 결과 객체를 가져온다.
|
|
5
|
+
from .result import ImageResult
|
|
6
|
+
|
|
7
|
+
# 패키지 외부에서 공개할 이름 목록
|
|
8
|
+
# 보통 "from image_api_sdk import *" 같은 상황에서 영향을 준다.
|
|
9
|
+
# 명시적으로 어떤 심볼을 공개 API로 볼지 보여주는 역할도 한다.
|
|
10
|
+
__all__ = ["ImageApiClient", "ImageApiError", "ImageResult"]
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
# 타입 힌트 편의용
|
|
3
|
+
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
# Any:
|
|
6
|
+
# dict 안에 어떤 값이 올지 폭넓게 허용할 때 사용
|
|
7
|
+
# Optional:
|
|
8
|
+
# int | None 같은 의미를 표현할 때 사용
|
|
9
|
+
|
|
10
|
+
import requests
|
|
11
|
+
# HTTP 요청을 보내기 위한 대표적인 파이썬 라이브러리
|
|
12
|
+
# 여기서는 서버의 /health, /api/v1/process를 호출하는 데 사용한다.
|
|
13
|
+
|
|
14
|
+
from .result import ImageResult
|
|
15
|
+
# 같은 패키지 안의 result.py에 정의한 ImageResult 클래스를 가져온다.
|
|
16
|
+
# 서버 응답(bytes)을 그냥 raw로 넘기지 않고, 사용하기 편한 객체로 감싸기 위함이다.
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ImageApiError(Exception):
|
|
20
|
+
"""
|
|
21
|
+
SDK 전용 예외 클래스.
|
|
22
|
+
|
|
23
|
+
그냥 ValueError나 RuntimeError를 쓰는 대신
|
|
24
|
+
ImageApiError를 만들어 두면,
|
|
25
|
+
SDK 사용자 입장에서 '이건 SDK/서버 요청 관련 오류구나' 하고 구분하기 쉽다.
|
|
26
|
+
|
|
27
|
+
사용 예:
|
|
28
|
+
try:
|
|
29
|
+
result = client.process_image(...)
|
|
30
|
+
except ImageApiError as e:
|
|
31
|
+
print("SDK 요청 실패:", e)
|
|
32
|
+
"""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ImageApiClient:
|
|
37
|
+
"""
|
|
38
|
+
이미지 처리 서버와 통신하는 클라이언트 클래스.
|
|
39
|
+
|
|
40
|
+
역할:
|
|
41
|
+
- 서버 주소(base_url)를 기억한다.
|
|
42
|
+
- /health 요청을 보내 서버 상태를 확인한다.
|
|
43
|
+
- /api/v1/process 요청을 보내 이미지 처리를 수행한다.
|
|
44
|
+
|
|
45
|
+
사용 예:
|
|
46
|
+
client = ImageApiClient("http://localhost:8080")
|
|
47
|
+
health = client.health()
|
|
48
|
+
result = client.process_image(...)
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, base_url: str, timeout: int = 30) -> None:
|
|
52
|
+
"""
|
|
53
|
+
클라이언트 객체 초기화.
|
|
54
|
+
|
|
55
|
+
매개변수:
|
|
56
|
+
- base_url : 서버 주소
|
|
57
|
+
예: "http://localhost:8080"
|
|
58
|
+
- timeout : 요청 타임아웃(초 단위)
|
|
59
|
+
|
|
60
|
+
rstrip("/")를 쓰는 이유:
|
|
61
|
+
- 사용자가 "http://localhost:8080/" 처럼 끝에 슬래시를 붙여도
|
|
62
|
+
- 내부에선 "http://localhost:8080" 형태로 통일하기 위해서다.
|
|
63
|
+
|
|
64
|
+
이렇게 하면 나중에
|
|
65
|
+
f"{self.base_url}/health"
|
|
66
|
+
같은 URL 조합을 할 때 // 중복을 피할 수 있다.
|
|
67
|
+
"""
|
|
68
|
+
self.base_url = base_url.rstrip("/")
|
|
69
|
+
self.timeout = timeout
|
|
70
|
+
|
|
71
|
+
def health(self) -> dict[str, Any]:
|
|
72
|
+
"""
|
|
73
|
+
서버의 /health 엔드포인트를 호출해 상태를 확인한다.
|
|
74
|
+
|
|
75
|
+
반환값:
|
|
76
|
+
- 서버가 돌려준 JSON(dict)
|
|
77
|
+
|
|
78
|
+
예상 응답 예:
|
|
79
|
+
{
|
|
80
|
+
"status": "ok",
|
|
81
|
+
"message": "server is running"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
동작 순서:
|
|
85
|
+
1. /health URL 생성
|
|
86
|
+
2. GET 요청 전송
|
|
87
|
+
3. HTTP 에러가 있으면 예외 발생
|
|
88
|
+
4. JSON 응답을 dict로 반환
|
|
89
|
+
"""
|
|
90
|
+
# 최종 요청 URL 생성
|
|
91
|
+
url = f"{self.base_url}/health"
|
|
92
|
+
|
|
93
|
+
# GET 요청 전송
|
|
94
|
+
response = requests.get(url, timeout=self.timeout)
|
|
95
|
+
|
|
96
|
+
# 4xx/5xx 응답이면 HTTPError 예외 발생
|
|
97
|
+
response.raise_for_status()
|
|
98
|
+
|
|
99
|
+
# JSON 응답을 파이썬 dict로 변환해 반환
|
|
100
|
+
return response.json()
|
|
101
|
+
|
|
102
|
+
def process_image(
|
|
103
|
+
self,
|
|
104
|
+
image_url: str,
|
|
105
|
+
operations: list[dict[str, Any]],
|
|
106
|
+
output_format: str = "jpg",
|
|
107
|
+
) -> ImageResult:
|
|
108
|
+
"""
|
|
109
|
+
서버에 이미지 처리 요청을 보내고 결과 이미지를 받아온다.
|
|
110
|
+
|
|
111
|
+
매개변수:
|
|
112
|
+
- image_url : 처리할 원본 이미지 URL
|
|
113
|
+
- operations : 순서대로 적용할 작업 목록
|
|
114
|
+
- output_format : 결과 이미지 포맷 (기본값: jpg)
|
|
115
|
+
|
|
116
|
+
사용 예:
|
|
117
|
+
result = client.process_image(
|
|
118
|
+
image_url="https://example.com/a.jpg",
|
|
119
|
+
operations=[
|
|
120
|
+
{"type": "grayscale"},
|
|
121
|
+
{"type": "blur", "options": {"ksize": 9, "sigma": 2.0}}
|
|
122
|
+
],
|
|
123
|
+
output_format="jpg"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
서버는 성공 시 이미지 바이트를 반환하고,
|
|
127
|
+
SDK는 그걸 ImageResult 객체로 감싸서 반환한다.
|
|
128
|
+
"""
|
|
129
|
+
# 처리 요청 엔드포인트 URL 생성
|
|
130
|
+
url = f"{self.base_url}/api/v1/process"
|
|
131
|
+
|
|
132
|
+
# 서버가 기대하는 JSON 요청 본문 구성
|
|
133
|
+
payload = {
|
|
134
|
+
"image_url": image_url,
|
|
135
|
+
"operations": operations,
|
|
136
|
+
"output_format": output_format,
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
# POST 요청 전송
|
|
140
|
+
# requests가 payload를 JSON으로 직렬화해서 보내고,
|
|
141
|
+
# Content-Type: application/json 헤더도 자동으로 넣어준다.
|
|
142
|
+
response = requests.post(url, json=payload, timeout=self.timeout)
|
|
143
|
+
|
|
144
|
+
# 응답 헤더에서 Content-Type 확인
|
|
145
|
+
# 성공 시 보통 image/jpeg 또는 image/png 같은 값이 올 것이다.
|
|
146
|
+
content_type = response.headers.get("Content-Type", "")
|
|
147
|
+
|
|
148
|
+
# HTTP 요청 실패(4xx, 5xx) 시
|
|
149
|
+
if not response.ok:
|
|
150
|
+
# 서버가 JSON 에러 메시지를 돌려줬을 수도 있으니 우선 JSON으로 읽어본다.
|
|
151
|
+
try:
|
|
152
|
+
error_json = response.json()
|
|
153
|
+
except Exception:
|
|
154
|
+
# JSON이 아니면 그냥 텍스트로 받아서 감싼다.
|
|
155
|
+
error_json = {"error": response.text}
|
|
156
|
+
|
|
157
|
+
# SDK 전용 예외 발생
|
|
158
|
+
raise ImageApiError(f"Request failed: {error_json}")
|
|
159
|
+
|
|
160
|
+
# 성공 응답인데도 image/*가 아니라면
|
|
161
|
+
# 우리가 기대한 형식이 아니므로 오류로 본다.
|
|
162
|
+
if not content_type.startswith("image/"):
|
|
163
|
+
raise ImageApiError(
|
|
164
|
+
f"Expected image response, but got Content-Type={content_type}"
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# 서버가 추가 헤더로 결과 이미지 크기를 보내주도록 만들었으므로 읽는다.
|
|
168
|
+
width_header = response.headers.get("X-Image-Width")
|
|
169
|
+
height_header = response.headers.get("X-Image-Height")
|
|
170
|
+
|
|
171
|
+
# 헤더가 있으면 int로 변환, 없으면 None
|
|
172
|
+
width: Optional[int] = int(width_header) if width_header else None
|
|
173
|
+
height: Optional[int] = int(height_header) if height_header else None
|
|
174
|
+
|
|
175
|
+
# response.content에는 실제 이미지 파일 bytes가 들어 있다.
|
|
176
|
+
# 이걸 ImageResult 객체로 감싸서 반환한다.
|
|
177
|
+
return ImageResult(
|
|
178
|
+
data=response.content,
|
|
179
|
+
mime_type=content_type,
|
|
180
|
+
width=width,
|
|
181
|
+
height=height,
|
|
182
|
+
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
# 위 문장은 타입 힌트를 더 유연하게 쓰기 위한 설정이다.
|
|
3
|
+
# 예를 들어 아직 정의 중인 클래스명을 타입으로 더 편하게 사용할 수 있다.
|
|
4
|
+
# 지금 코드에선 꼭 필수는 아니지만, 요즘 파이썬 코드에서 자주 넣는다.
|
|
5
|
+
|
|
6
|
+
import base64
|
|
7
|
+
# 이미지 바이트를 base64 문자열로 바꿀 때 사용한다.
|
|
8
|
+
# 예: DB text/json 컬럼 저장, 웹 전송용 문자열화 등에 쓸 수 있다.
|
|
9
|
+
|
|
10
|
+
import io
|
|
11
|
+
# 메모리 안의 bytes 데이터를 파일처럼 다루기 위해 사용한다.
|
|
12
|
+
# Pillow가 BytesIO 객체를 통해 이미지 열 수 있다.
|
|
13
|
+
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
# dataclass를 쓰면 __init__, __repr__ 같은 기본 메서드를 자동으로 만들어준다.
|
|
16
|
+
# 결과 객체를 간단하고 깔끔하게 정의할 수 있다.
|
|
17
|
+
|
|
18
|
+
from typing import Optional
|
|
19
|
+
# Optional[int]는 int 또는 None을 뜻한다.
|
|
20
|
+
# 예: width가 없을 수도 있으니 Optional[int]로 표현
|
|
21
|
+
|
|
22
|
+
from PIL import Image
|
|
23
|
+
# Pillow 라이브러리의 Image 객체
|
|
24
|
+
# 이미지 표시, 저장, 조작 등에 편리하다.
|
|
25
|
+
|
|
26
|
+
import numpy as np
|
|
27
|
+
# 이미지를 numpy 배열로 바꿔서 다른 라이브러리와 연동하기 좋다.
|
|
28
|
+
# 예: 머신러닝 입력, 수치 처리 등
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class ImageResult:
|
|
33
|
+
"""
|
|
34
|
+
서버가 반환한 결과 이미지를 감싸는 객체.
|
|
35
|
+
|
|
36
|
+
이 클래스는 단순히 bytes만 들고 있는 게 아니라,
|
|
37
|
+
개발자가 바로 활용할 수 있도록 여러 편의 메서드를 제공한다.
|
|
38
|
+
|
|
39
|
+
필드 설명:
|
|
40
|
+
- data : 실제 이미지 파일 바이트 (jpg/png 등)
|
|
41
|
+
- mime_type : 서버가 알려준 MIME 타입
|
|
42
|
+
예: image/jpeg, image/png
|
|
43
|
+
- width : 결과 이미지 가로 크기 (없을 수도 있음)
|
|
44
|
+
- height : 결과 이미지 세로 크기 (없을 수도 있음)
|
|
45
|
+
"""
|
|
46
|
+
data: bytes
|
|
47
|
+
mime_type: str
|
|
48
|
+
width: Optional[int] = None
|
|
49
|
+
height: Optional[int] = None
|
|
50
|
+
|
|
51
|
+
def save(self, path: str) -> None:
|
|
52
|
+
"""
|
|
53
|
+
결과 이미지 바이트를 파일로 저장하는 메서드.
|
|
54
|
+
|
|
55
|
+
사용 예:
|
|
56
|
+
result.save("output.jpg")
|
|
57
|
+
|
|
58
|
+
동작:
|
|
59
|
+
- 바이너리 쓰기 모드("wb")로 파일을 열고
|
|
60
|
+
- self.data 내용을 그대로 저장한다.
|
|
61
|
+
"""
|
|
62
|
+
with open(path, "wb") as f:
|
|
63
|
+
f.write(self.data)
|
|
64
|
+
|
|
65
|
+
def to_bytes(self) -> bytes:
|
|
66
|
+
"""
|
|
67
|
+
결과 이미지를 raw bytes 형태로 그대로 반환한다.
|
|
68
|
+
|
|
69
|
+
사용 예:
|
|
70
|
+
image_bytes = result.to_bytes()
|
|
71
|
+
|
|
72
|
+
이 bytes는:
|
|
73
|
+
- 파일로 저장할 수도 있고
|
|
74
|
+
- DB BLOB에 넣을 수도 있고
|
|
75
|
+
- 다른 API로 전달할 수도 있다.
|
|
76
|
+
"""
|
|
77
|
+
return self.data
|
|
78
|
+
|
|
79
|
+
def to_base64(self) -> str:
|
|
80
|
+
"""
|
|
81
|
+
결과 이미지 바이트를 base64 문자열로 변환한다.
|
|
82
|
+
|
|
83
|
+
사용 예:
|
|
84
|
+
b64 = result.to_base64()
|
|
85
|
+
|
|
86
|
+
base64는:
|
|
87
|
+
- JSON에 넣기 편하고
|
|
88
|
+
- 텍스트 기반 저장소에 넣기 쉽다.
|
|
89
|
+
|
|
90
|
+
동작:
|
|
91
|
+
1. self.data(bytes)를 base64 bytes로 인코딩
|
|
92
|
+
2. 다시 utf-8 문자열로 디코딩해서 str로 반환
|
|
93
|
+
"""
|
|
94
|
+
return base64.b64encode(self.data).decode("utf-8")
|
|
95
|
+
|
|
96
|
+
def to_pil(self) -> Image.Image:
|
|
97
|
+
"""
|
|
98
|
+
결과 이미지를 Pillow Image 객체로 변환한다.
|
|
99
|
+
|
|
100
|
+
사용 예:
|
|
101
|
+
pil_img = result.to_pil()
|
|
102
|
+
pil_img.show()
|
|
103
|
+
|
|
104
|
+
동작:
|
|
105
|
+
- self.data는 단순 bytes이므로
|
|
106
|
+
- io.BytesIO로 '메모리 파일'처럼 감싼다.
|
|
107
|
+
- Pillow의 Image.open()으로 연다.
|
|
108
|
+
"""
|
|
109
|
+
return Image.open(io.BytesIO(self.data))
|
|
110
|
+
|
|
111
|
+
def to_numpy(self) -> np.ndarray:
|
|
112
|
+
"""
|
|
113
|
+
결과 이미지를 numpy 배열로 변환한다.
|
|
114
|
+
|
|
115
|
+
사용 예:
|
|
116
|
+
arr = result.to_numpy()
|
|
117
|
+
|
|
118
|
+
보통 shape는 이런 식이다:
|
|
119
|
+
- 컬러 이미지: (height, width, channel)
|
|
120
|
+
- 흑백 이미지: (height, width)
|
|
121
|
+
|
|
122
|
+
동작:
|
|
123
|
+
- 먼저 Pillow Image로 연다.
|
|
124
|
+
- 그걸 np.array(...)로 변환한다.
|
|
125
|
+
"""
|
|
126
|
+
return np.array(self.to_pil())
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: image-api-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for a C++ image processing API server
|
|
5
|
+
Author: seje06
|
|
6
|
+
License: LICENSE
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: requests>=2.31.0
|
|
11
|
+
Requires-Dist: pillow>=10.0.0
|
|
12
|
+
Requires-Dist: numpy>=1.24.0
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# cv_api_python_sdk
|
|
16
|
+
이미지 처리를 해주는 cv api 서버를 활용하기 위한 파이썬 라이브러리 개발
|
|
17
|
+
|
|
18
|
+
## 세팅
|
|
19
|
+
|
|
20
|
+
1. 가상환경
|
|
21
|
+
```bash
|
|
22
|
+
> python -m venv .venv
|
|
23
|
+
> .venv\Scripts\activate
|
|
24
|
+
```
|
|
25
|
+
2. 필요 라이브러리 설치
|
|
26
|
+
```bash
|
|
27
|
+
> pip install requests pillow numpy
|
|
28
|
+
> pip freeze > requirements.txt
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 라이브러리화
|
|
32
|
+
|
|
33
|
+
- 구조
|
|
34
|
+
```text
|
|
35
|
+
cv_api_python_sdk/
|
|
36
|
+
├─ image_api_sdk/
|
|
37
|
+
│ ├─ __init__.py
|
|
38
|
+
│ ├─ client.py
|
|
39
|
+
│ └─ result.py
|
|
40
|
+
├─ examples/
|
|
41
|
+
│ └─ basic_example.py
|
|
42
|
+
├─ README.md
|
|
43
|
+
├─ LICENSE
|
|
44
|
+
├─ pyproject.toml
|
|
45
|
+
└─ requirements.txt
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### 필요 파일 작성
|
|
50
|
+
|
|
51
|
+
- pyproject.toml - [작성파일](pyproject.toml)
|
|
52
|
+
- 프로젝트의 모든 설정과 배포 명세서를 담은 표준 지도
|
|
53
|
+
|
|
54
|
+
- LICENSE - [작성파일](LICENSE)
|
|
55
|
+
- 프로젝트를 사용하는 사람들에게 주는 허가증(권리 증명서) 역할
|
|
56
|
+
|
|
57
|
+
### 필요 라이브러리 설치 및 실행
|
|
58
|
+
|
|
59
|
+
1. 배포파일 생성
|
|
60
|
+
```bash
|
|
61
|
+
pip install build
|
|
62
|
+
python -m build
|
|
63
|
+
```
|
|
64
|
+
2. 다른 가상환경에서 테스트
|
|
65
|
+
- bash
|
|
66
|
+
``` bash
|
|
67
|
+
pip install (프로젝트의 부모절대경로)\cv_api_python_sdk\dist\image_api_sdk-0.1.0-py3-none-any.whl
|
|
68
|
+
```
|
|
69
|
+
- python
|
|
70
|
+
```python
|
|
71
|
+
from image_api_sdk import ImageApiClient
|
|
72
|
+
print("import success")
|
|
73
|
+
```
|
|
74
|
+
3. PYPI(공용파이썬 라이브러리 저장소) 에 올리기
|
|
75
|
+
- twine 설치
|
|
76
|
+
```bash
|
|
77
|
+
pip install twine
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
## 예시 사용법
|
|
82
|
+
|
|
83
|
+
- 설치
|
|
84
|
+
```bash
|
|
85
|
+
pip install image-api-sdk
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- [예시코드](./examples/basic_example.py)
|
|
89
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
image_api_sdk/__init__.py
|
|
5
|
+
image_api_sdk/client.py
|
|
6
|
+
image_api_sdk/result.py
|
|
7
|
+
image_api_sdk.egg-info/PKG-INFO
|
|
8
|
+
image_api_sdk.egg-info/SOURCES.txt
|
|
9
|
+
image_api_sdk.egg-info/dependency_links.txt
|
|
10
|
+
image_api_sdk.egg-info/requires.txt
|
|
11
|
+
image_api_sdk.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
image_api_sdk
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "image-api-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for a C++ image processing API server"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "LICENSE" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "seje06" }
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"requests>=2.31.0",
|
|
17
|
+
"pillow>=10.0.0",
|
|
18
|
+
"numpy>=1.24.0"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.setuptools]
|
|
22
|
+
packages = ["image_api_sdk"]
|