Skip to content

Commit ba3b89a

Browse files
aereminaKochankovIDrestyled-io[bot]restyled-commits
authored
Added correction of white balance (#11)
* Added correction of white balance * Added fixture for test * fabric * fix linters, update code feat: new v3 api * Restyle Added correction of white balance (#13) * Restyled by autopep8 * Restyled by isort * Restyled by reorder-python-imports * Restyled by yapf Co-authored-by: Restyled.io <[email protected]> * fix ci/cd python version * fix ci/cd python version * fix imports * Restyle Added correction of white balance (#14) * Restyled by autopep8 * Restyled by black * Restyled by isort * Restyled by reorder-python-imports * Restyled by yapf Co-authored-by: Restyled.io <[email protected]> * fix ci/cd * Restyle Added correction of white balance (#15) * Restyled by yapf * Restyled by black * Restyled by isort Co-authored-by: Restyled.io <[email protected]> * verbose pytest * pytest all close * pytest all close * pytest all close Co-authored-by: ilyakochankov <[email protected]> Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com> Co-authored-by: Restyled.io <[email protected]>
1 parent d1afc21 commit ba3b89a

25 files changed

+333
-49
lines changed

.github/workflows/bandit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Set up Python 3.9
1616
uses: actions/setup-python@v2
1717
with:
18-
python-version: 3.9
18+
python-version: 3.9.8
1919

2020
- name: Install bandit
2121
run: |

.github/workflows/black.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Python 3.9
1919
uses: actions/setup-python@v2
2020
with:
21-
python-version: 3.9
21+
python-version: 3.9.8
2222
#----------------------------------------------
2323
# ----- install & configure poetry -----
2424
#----------------------------------------------
@@ -40,6 +40,6 @@ jobs:
4040
- name: Analysing the vendor service code with black
4141
run: |
4242
source .venv/bin/activate
43-
black .
43+
black --check .
4444
deactivate
4545
exit ${exit_code}

.github/workflows/codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Set up Python 3.9
2323
uses: actions/setup-python@v2
2424
with:
25-
python-version: 3.9
25+
python-version: 3.9.8
2626
#----------------------------------------------
2727
# ----- install & configure poetry -----
2828
#----------------------------------------------

.github/workflows/flake8.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Python 3.9
1919
uses: actions/setup-python@v2
2020
with:
21-
python-version: 3.9
21+
python-version: 3.9.8
2222
#----------------------------------------------
2323
# ----- install & configure poetry -----
2424
#----------------------------------------------

.github/workflows/isort.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Python 3.9
1919
uses: actions/setup-python@v2
2020
with:
21-
python-version: 3.9
21+
python-version: 3.9.8
2222
#----------------------------------------------
2323
# ----- install & configure poetry -----
2424
#----------------------------------------------
@@ -40,6 +40,6 @@ jobs:
4040
- name: Analysing the vendor service code with isort
4141
run: |
4242
source .venv/bin/activate
43-
isort .
43+
isort --check .
4444
deactivate
4545
exit ${exit_code}

.github/workflows/pylint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- name: Set up Python 3.9
1919
uses: actions/setup-python@v2
2020
with:
21-
python-version: 3.9
21+
python-version: 3.9.8
2222
#----------------------------------------------
2323
# ----- install & configure poetry -----
2424
#----------------------------------------------

.github/workflows/pytest.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Set up Python 3.9
2323
uses: actions/setup-python@v2
2424
with:
25-
python-version: 3.9
25+
python-version: 3.9.8
2626
#----------------------------------------------
2727
# ----- install & configure poetry -----
2828
#----------------------------------------------
@@ -41,5 +41,5 @@ jobs:
4141
- name: Run tests
4242
run: |
4343
source .venv/bin/activate
44-
pytest
44+
pytest -v
4545
deactivate

.restyled.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
enabled: true
2+
pull_requests: true
3+
statuses:
4+
differences: true # Red when style differences are found
5+
no_differences: true # Green when no differences are found
6+
error: true
7+
restylers_version: stable
8+
restylers:
9+
- "*"
10+
- autopep8:
11+
enabled: false
12+
- black:
13+
arguments:
14+
- "--config"
15+
- "pyproject.toml"
16+
- isort:
17+
arguments:
18+
- "--sp"
19+
- "."

api/v3/cv/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from flask import Blueprint
2+
3+
bp = Blueprint("cv_v3", __name__, url_prefix="/api/cv/v3") # type: Blueprint
4+
5+
from api.v3.cv.tonal import *

api/v3/cv/tonal.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import http
2+
from typing import Optional
3+
4+
import numpy as np
5+
from cv2 import cv2
6+
from flask_apispec import doc, marshal_with, use_kwargs
7+
from marshmallow import fields, validate
8+
from werkzeug.datastructures import FileStorage
9+
10+
from api.v3.cv import bp
11+
from schemas.color_schema import ColorSchema
12+
from schemas.error_schema import ErrorSchema
13+
from schemas.input_image_schema import InputImageSchema
14+
from services.cv_tone_processor import CVToneProcessor
15+
from services.face_extractor import face_extractor_fabric
16+
from services.tone_extractor import tone_extractor_fabric
17+
from services.white_balance import white_balance_fabric
18+
19+
20+
@bp.route("/skin_tone", methods=["POST"])
21+
@doc(
22+
description="Search face on the photo and determine its skin color",
23+
tags=["tonal"],
24+
consumes=["multipart/form-data"],
25+
)
26+
@use_kwargs(InputImageSchema, location="files")
27+
@use_kwargs(
28+
{
29+
"wb": fields.String(
30+
default=None, validate=validate.OneOf(white_balance_fabric.keys())
31+
)
32+
},
33+
location="query",
34+
)
35+
@use_kwargs(
36+
{
37+
"face_ext": fields.String(
38+
default="mediapipe", validate=validate.OneOf(face_extractor_fabric.keys())
39+
)
40+
},
41+
location="query",
42+
)
43+
@use_kwargs(
44+
{
45+
"tone_ext": fields.String(
46+
default="kmean", validate=validate.OneOf(tone_extractor_fabric.keys())
47+
)
48+
},
49+
location="query",
50+
)
51+
@marshal_with(schema=ColorSchema, code=200, description="Return color in hex code")
52+
@marshal_with(schema=ErrorSchema, code=422, description="Problem with image file")
53+
@marshal_with(schema=ErrorSchema, code=400, description="No face on the image")
54+
def skin_tone_v3(
55+
image: FileStorage,
56+
face_ext: str = "mediapipe",
57+
tone_ext: str = "kmean",
58+
wb: Optional[str] = None,
59+
):
60+
np_img = np.fromstring(image.read(), np.uint8)
61+
image = cv2.imdecode(np_img, cv2.IMREAD_COLOR)
62+
color = CVToneProcessor.build_tone_process(image, face_ext, tone_ext, wb)
63+
64+
if not color:
65+
error = {"files": {"image": ["No face on the image"]}}
66+
return ErrorSchema().dump({"error": error}), http.HTTPStatus.BAD_REQUEST
67+
68+
response = dict(color=color)
69+
return ColorSchema().dump(response)

core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from environs import Env
44

55
env = Env()
6-
env.read_env('.env')
6+
env.read_env(".env")
77

88
# Build paths inside the project like this: BASE_DIR / 'subdir'.
99
BASE_DIR = Path(__file__).resolve().parent.parent

main.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from api.v1.cv.tonal import opencv_skin_tone_v1
1313
from api.v2.cv import bp as cv_bp_v2
1414
from api.v2.cv.tonal import mediapipe_skin_tone_v2, opencv_skin_tone_v2
15+
from api.v3.cv import bp as cv_bp_v3
16+
from api.v3.cv.tonal import skin_tone_v3
1517
from core import settings
1618
from core.loger import LOGGING
1719
from core.settings import CV_ALLOWED_HOSTS, DEBUG
@@ -71,9 +73,11 @@ def health_check():
7173

7274
app.register_blueprint(cv_bp_v1)
7375
app.register_blueprint(cv_bp_v2)
76+
app.register_blueprint(cv_bp_v3)
7477
docs.register(opencv_skin_tone_v1, blueprint=cv_bp_v1.name)
7578
docs.register(opencv_skin_tone_v2, blueprint=cv_bp_v2.name)
7679
docs.register(mediapipe_skin_tone_v2, blueprint=cv_bp_v2.name)
80+
docs.register(skin_tone_v3, blueprint=cv_bp_v3.name)
7781
docs.register(health_check)
7882

7983

poetry.lock

Lines changed: 34 additions & 34 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mediapipe = "^0.8.8"
2020
six = "^1.16.0"
2121
Flask-Cors = "^3.0.10"
2222
typing-extensions = "^3.10.0"
23-
opencv-python-headless = "^4.5.4"
23+
opencv-contrib-python-headless = "^4.5.4"
2424

2525
[tool.poetry.dev-dependencies]
2626
pylint = "2.9.3"
@@ -59,7 +59,8 @@ disable = [
5959
"no-name-in-module",
6060
"c-extension-no-member",
6161
"duplicate-code",
62-
"inconsistent-return-statements"
62+
"inconsistent-return-statements",
63+
"import-error"
6364
]
6465

6566
[tool.isort]
@@ -70,7 +71,7 @@ ignore = ["E203", "W503"]
7071
max-line-length = 120
7172
format = "html"
7273
htmldir = "flake-report"
73-
exclude = [".venv", "api/v1/cv/__init__.py", "api/v2/cv/__init__.py"]
74+
exclude = [".venv", "api/v1/cv/__init__.py", "api/v2/cv/__init__.py", "api/v3/cv/__init__.py"]
7475

7576
[tool.pytest.ini_options]
7677
minversion = "6.0"

services/chain/cell.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
from typing import Any
33

44

5+
class CellError(Exception):
6+
...
7+
8+
59
class Cell(ABC):
610
@abstractmethod
711
def set_next(self, next_cell: "Cell") -> "Cell":
@@ -27,4 +31,7 @@ def __call__(self, context: Any):
2731

2832
class CellFromFabric(AbstractCell):
2933
def __init__(self, fabric: dict, item_name: str):
30-
self._item = fabric[item_name]
34+
try:
35+
self._item = fabric[item_name]
36+
except KeyError as e:
37+
raise CellError(str(e)) from KeyError

services/cv_tone_processor.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from services.cv_context import CVContext
88
from services.face_extractor import FaceExtractorCell
99
from services.tone_extractor import ToneExtractorCell
10+
from services.white_balance import WhiteBalanceCell
1011

1112

1213
class CVToneProcessor:
@@ -33,3 +34,21 @@ def mediapipe_tone_process(image: np.ndarray) -> Optional[str]:
3334
)
3435
context: CVContext = chain.process(CVContext(image))
3536
return context.tone_hex
37+
38+
@staticmethod
39+
def build_tone_process(
40+
image: np.ndarray, face_ext: str, tone_ext: str, wb: Optional[str] = None
41+
):
42+
cells = []
43+
if wb:
44+
cells.append(WhiteBalanceCell(white_balance=wb))
45+
cells.extend(
46+
[
47+
FaceExtractorCell(face_extractor=face_ext),
48+
ToneExtractorCell(tone_extractor=tone_ext),
49+
R2HConverterCell(),
50+
]
51+
)
52+
chain = Chain(cells=cells)
53+
context: CVContext = chain.process(CVContext(image))
54+
return context.tone_hex

0 commit comments

Comments
 (0)