diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..2ba8ed5
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,47 @@
+# Ignorar arquivos e diretórios irrelevantes
+*.pyc
+*.pyo
+*.pyd
+__pycache__/
+*.log
+*.tmp
+*.swp
+
+# Ignorar arquivos de controle de versão
+.git/
+*.gitignore
+
+# Ignorar ambientes virtuais e pacotes locais
+.env/
+*.env
+*.tar
+*.zip
+*.rar
+recorte-placas-env/
+
+# Ignorar imagens e arquivos grandes
+*.jpg
+*.png
+photos/
+processed_photos/
+
+# Ignorar outros arquivos desnecessários
+*.tar
+*.bak
+*.old
+*.DS_Store
+*.idea
+*.vscode
+
+# Incluir arquivos essenciais explicitamente
+!Dockerfile
+!requirements.txt
+!imageProcAPI.py
+!workflow.py
+!scan.py
+!teste.py
+
+# Incluir pastas essenciais explicitamente
+!connection/
+!pyimagesearch/
+!utils/
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 058598c..472de1a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,9 @@
*.pyc
-.DS_Store
\ No newline at end of file
+.DS_Store
+images/
+output/
+recorte-placas-env/
+photos/
+processed_photos/
+python-image/
+recorte-placas.tar
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..494b9b2
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,31 @@
+# Use a imagem oficial do Python mais leve
+FROM python:3.8-slim
+
+# Defina um ambiente não interativo para evitar prompts do apt
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Instale dependências essenciais do sistema
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ build-essential \
+ libopencv-dev \
+ && apt-get clean && rm -rf /var/lib/apt/lists/*
+
+# Defina o diretório de trabalho dentro do container
+WORKDIR /app
+
+# Copie e instale apenas as dependências antes para aproveitar o cache do Docker
+COPY requirements.txt .
+RUN pip install --no-cache-dir -r requirements.txt
+
+# Copie o restante do código da aplicação
+COPY . .
+
+# Exponha a porta que o Flask usará
+EXPOSE 5000
+
+# Defina variáveis de ambiente para produção
+ENV FLASK_APP=imageProcAPI.py
+ENV FLASK_RUN_HOST=0.0.0.0
+
+# Execute o servidor Flask diretamente para melhor compatibilidade
+CMD ["python", "-m", "flask", "run", "--host=0.0.0.0"]
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 9ce8d29..0000000
--- a/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Document Scanner
-
-### An interactive document scanner built in Python using OpenCV
-
-The scanner takes a poorly scanned image, finds the corners of the document, applies the perspective transformation to get a top-down view of the document, sharpens the image, and applies an adaptive color threshold to clean up the image.
-
-On my test dataset of 280 images, the program correctly detected the corners of the document 92.8% of the time.
-
-This project makes use of the transform and imutils modules from pyimagesearch (which can be accessed [here](http://www.pyimagesearch.com/2014/09/01/build-kick-ass-mobile-document-scanner-just-5-minutes/)). The UI code for the interactive mode is adapted from `poly_editor.py` from [here](https://matplotlib.org/examples/event_handling/poly_editor.html).
-
-* You can manually click and drag the corners of the document to be perspective transformed:
-
-
-* The scanner can also process an entire directory of images automatically and save the output in an output directory:
-
-
-#### Here are some examples of images before and after scan:
-
-
-
-
-
-
-
-
-
-### Usage
-```
-python scan.py (--images | --image ) [-i]
-```
-* The `-i` flag enables interactive mode, where you will be prompted to click and drag the corners of the document. For example, to scan a single image with interactive mode enabled:
-```
-python scan.py --image sample_images/desk.JPG -i
-```
-* Alternatively, to scan all images in a directory without any input:
-```
-python scan.py --images sample_images
-```
diff --git a/before_after.gif b/before_after.gif
deleted file mode 100644
index 6bb31de..0000000
Binary files a/before_after.gif and /dev/null differ
diff --git a/connection/patch.py b/connection/patch.py
new file mode 100644
index 0000000..1762b14
--- /dev/null
+++ b/connection/patch.py
@@ -0,0 +1,23 @@
+import requests
+
+def patch(id, photo_url):
+
+ url = f"https://tfiswpjimraodvnjbybx.supabase.co/rest/v1/Boards?id=eq.{id}"
+ headers = { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRmaXN3cGppbXJhb2R2bmpieWJ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMxNTIwNTUsImV4cCI6MjA0ODcyODA1NX0.I8UX36hAphowNk85VcL6iYh4TIBwsE0r3wgreTEDaII",
+ "apikey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRmaXN3cGppbXJhb2R2bmpieWJ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMxNTIwNTUsImV4cCI6MjA0ODcyODA1NX0.I8UX36hAphowNk85VcL6iYh4TIBwsE0r3wgreTEDaII",
+ "Prefer": "return=representation"
+ }
+
+ data = {
+ "trimmed_photo_url": photo_url
+ }
+
+
+ response = requests.patch(url, json=data, headers=headers)
+
+ if response.status_code in [200, 204]:
+ print("Atualização feita com sucesso!")
+ print(response.json()) # Caso a API retorne um JSON
+ else:
+ print(f"Erro ao atualizar: {response.status_code}")
+ print(response.text) # Exibir a resposta do servidor
diff --git a/connection/supabase_connection.py b/connection/supabase_connection.py
new file mode 100644
index 0000000..204b6ae
--- /dev/null
+++ b/connection/supabase_connection.py
@@ -0,0 +1,46 @@
+import requests
+
+class SupabaseConnection:
+ """
+ Classe para gerenciar a conexão e upload de arquivos para o Supabase Storage.
+ """
+
+ def __init__(self):
+ """
+ Inicializa a conexão com os parâmetros fornecidos.
+
+ :param supabase_url: URL do Supabase
+ :param bucket_name: Nome do bucket no Supabase
+ :param file_key: Caminho onde será salvo no Supabase
+ :param file_path: Caminho do arquivo local
+ :param jwt_token: JWT Token para autenticação
+ """
+ self.supabase_url = "https://tfiswpjimraodvnjbybx.supabase.co"
+ self.bucket_name = "boards"
+ self.jwt_token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRmaXN3cGppbXJhb2R2bmpieWJ4Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMxNTIwNTUsImV4cCI6MjA0ODcyODA1NX0.I8UX36hAphowNk85VcL6iYh4TIBwsE0r3wgreTEDaII"
+ self.headers = {
+ "Authorization": f"{self.jwt_token}",
+ "Content-Type": "image/jpeg"
+ }
+
+ def upload_file_to_supabase(self, image_name, image_path):
+ """
+ Faz o upload do arquivo para o Supabase Storage.
+ """
+ upload_url = f"{self.supabase_url}/storage/v1/object/{self.bucket_name}/images/{image_name}"
+
+ try:
+ with open(image_path, "rb") as file:
+ response = requests.put(upload_url, headers=self.headers, data=file)
+
+ # Verificar resposta
+ if response.status_code == 200:
+ print(f"✅ Upload bem-sucedido! Arquivo salvo como: images/{image_name}")
+ response_json = response.json()
+ response_json.update({"url": f"{upload_url}"})
+ return response_json
+ else:
+ print(f"❌ Erro no upload: {response.status_code} - {response.text}")
+
+ except Exception as e:
+ print("❌ Erro ao enviar a imagem:", e)
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..8f37bad
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,14 @@
+version: '3.8' # Versão do Docker Compose
+
+services:
+ flask_app: # Nome do serviço (pode ser qualquer nome)
+ build: . # Indica que o Dockerfile está no diretório atual
+ container_name: flask_container # Nome do contêiner (opcional)
+ ports:
+ - "5000:5000" # Mapeia a porta 5000 do contêiner para a porta 5000 do host
+ environment:
+ - FLASK_APP=imageProcAPI.py # Define a variável de ambiente FLASK_APP
+ - FLASK_RUN_HOST=0.0.0.0 # Define a variável de ambiente FLASK_RUN_HOST
+ volumes:
+ - .:/app # Monta o diretório atual do host no diretório /app do contêiner (útil para desenvolvimento)
+ restart: unless-stopped # Reinicia o contêiner automaticamente, a menos que seja parado manualmente
\ No newline at end of file
diff --git a/imageProcAPI.py b/imageProcAPI.py
new file mode 100644
index 0000000..e12aa61
--- /dev/null
+++ b/imageProcAPI.py
@@ -0,0 +1,59 @@
+from flask import Flask, request, jsonify
+from workflow import workImage
+import threading
+import time
+import random
+import string
+
+app = Flask(__name__)
+
+image_queue = [] # Lista para armazenar as URLs da fila
+processing = False # Flag para indicar se há uma imagem sendo processada
+
+def process_next_image():
+ global processing
+ while True:
+ if image_queue and not processing:
+ processing = True
+ image_data = image_queue.pop(0)
+ image_name = image_data["image_name"]
+ print(f"Processando imagem: {image_name}")
+
+ # Processa a imagem e obtém os dados da imagem no bucket
+ workImage(image_data["photo_url"], image_name, image_data["id"])
+
+ processing = False
+ time.sleep(1) # Pequeno delay para evitar loop intenso
+
+def generate_random_name(length=10):
+ letters = string.ascii_lowercase
+ image_name = ''.join(random.choice(letters) for _ in range(length))
+ return image_name + ".jpg"
+
+@app.route("/")
+def imageURL():
+ return "API de Processamento de Imagens - Online"
+
+@app.route("/create-procimage", methods=["POST"])
+def create_procimage():
+ data = request.get_json()
+
+ if "photo_url" not in data:
+ return jsonify({"error": "Parâmetro 'photo_url' é obrigatório"}), 400
+
+ if "id" not in data:
+ return jsonify({"error": "Parâmetro 'id' é obrigatório"}), 400
+
+ image_name = generate_random_name()
+ data["image_name"] = image_name
+ image_queue.append(data)
+ print(f"Imagem recebida e adicionada na fila com nome: {data['image_name']}")
+
+ return jsonify({"status": "ok", "image_name": image_name, "processed_image_url": f"https://tfiswpjimraodvnjbybx.supabase.co/storage/v1/object/boards/images/{image_name}"}), 201
+
+if __name__ == "__main__":
+ # Iniciar a thread para processar a fila em background
+ processing_thread = threading.Thread(target=process_next_image, daemon=True)
+ processing_thread.start()
+
+ app.run(host="0.0.0.0", debug=True)
diff --git a/output/cell_pic.jpg b/output/cell_pic.jpg
deleted file mode 100644
index edea3a3..0000000
Binary files a/output/cell_pic.jpg and /dev/null differ
diff --git a/output/chart.JPG b/output/chart.JPG
deleted file mode 100644
index 11bffdd..0000000
Binary files a/output/chart.JPG and /dev/null differ
diff --git a/output/desk.JPG b/output/desk.JPG
deleted file mode 100644
index c4f6373..0000000
Binary files a/output/desk.JPG and /dev/null differ
diff --git a/output/dollar_bill.JPG b/output/dollar_bill.JPG
deleted file mode 100644
index 82daeb1..0000000
Binary files a/output/dollar_bill.JPG and /dev/null differ
diff --git a/output/math_cheat_sheet.JPG b/output/math_cheat_sheet.JPG
deleted file mode 100644
index e97451e..0000000
Binary files a/output/math_cheat_sheet.JPG and /dev/null differ
diff --git a/output/notepad.JPG b/output/notepad.JPG
deleted file mode 100644
index 2990c84..0000000
Binary files a/output/notepad.JPG and /dev/null differ
diff --git a/output/receipt.jpg b/output/receipt.jpg
deleted file mode 100644
index 6fba926..0000000
Binary files a/output/receipt.jpg and /dev/null differ
diff --git a/output/tax.jpeg b/output/tax.jpeg
deleted file mode 100644
index 3db7423..0000000
Binary files a/output/tax.jpeg and /dev/null differ
diff --git a/polygon_interacter.py b/polygon_interacter.py
deleted file mode 100644
index 66b3e1e..0000000
--- a/polygon_interacter.py
+++ /dev/null
@@ -1,106 +0,0 @@
-import numpy as np
-from matplotlib.lines import Line2D
-from matplotlib.artist import Artist
-
-
-class PolygonInteractor(object):
- """
- An polygon editor
- """
-
- showverts = True
- epsilon = 5 # max pixel distance to count as a vertex hit
-
- def __init__(self, ax, poly):
- if poly.figure is None:
- raise RuntimeError('You must first add the polygon to a figure or canvas before defining the interactor')
- self.ax = ax
- canvas = poly.figure.canvas
- self.poly = poly
-
- x, y = zip(*self.poly.xy)
- self.line = Line2D(x, y, marker='o', markerfacecolor='r', animated=True)
- self.ax.add_line(self.line)
-
- cid = self.poly.add_callback(self.poly_changed)
- self._ind = None # the active vert
-
- canvas.mpl_connect('draw_event', self.draw_callback)
- canvas.mpl_connect('button_press_event', self.button_press_callback)
- canvas.mpl_connect('button_release_event', self.button_release_callback)
- canvas.mpl_connect('motion_notify_event', self.motion_notify_callback)
- self.canvas = canvas
-
- def get_poly_points(self):
- return np.asarray(self.poly.xy)
-
- def draw_callback(self, event):
- self.background = self.canvas.copy_from_bbox(self.ax.bbox)
- self.ax.draw_artist(self.poly)
- self.ax.draw_artist(self.line)
- self.canvas.blit(self.ax.bbox)
-
- def poly_changed(self, poly):
- 'this method is called whenever the polygon object is called'
- # only copy the artist props to the line (except visibility)
- vis = self.line.get_visible()
- Artist.update_from(self.line, poly)
- self.line.set_visible(vis) # don't use the poly visibility state
-
- def get_ind_under_point(self, event):
- 'get the index of the vertex under point if within epsilon tolerance'
-
- # display coords
- xy = np.asarray(self.poly.xy)
- xyt = self.poly.get_transform().transform(xy)
- xt, yt = xyt[:, 0], xyt[:, 1]
- d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
- indseq = np.nonzero(np.equal(d, np.amin(d)))[0]
- ind = indseq[0]
-
- if d[ind] >= self.epsilon:
- ind = None
-
- return ind
-
- def button_press_callback(self, event):
- 'whenever a mouse button is pressed'
- if not self.showverts:
- return
- if event.inaxes is None:
- return
- if event.button != 1:
- return
- self._ind = self.get_ind_under_point(event)
-
- def button_release_callback(self, event):
- 'whenever a mouse button is released'
- if not self.showverts:
- return
- if event.button != 1:
- return
- self._ind = None
-
- def motion_notify_callback(self, event):
- 'on mouse movement'
- if not self.showverts:
- return
- if self._ind is None:
- return
- if event.inaxes is None:
- return
- if event.button != 1:
- return
- x, y = event.xdata, event.ydata
-
- self.poly.xy[self._ind] = x, y
- if self._ind == 0:
- self.poly.xy[-1] = x, y
- elif self._ind == len(self.poly.xy) - 1:
- self.poly.xy[0] = x, y
- self.line.set_data(zip(*self.poly.xy))
-
- self.canvas.restore_region(self.background)
- self.ax.draw_artist(self.poly)
- self.ax.draw_artist(self.line)
- self.canvas.blit(self.ax.bbox)
diff --git a/pyimagesearch/__init__.py b/pyimagesearch/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/requirements.txt b/requirements.txt
index 6c24c69..90e7a3d 100644
Binary files a/requirements.txt and b/requirements.txt differ
diff --git a/sample_images/cell_pic.jpg b/sample_images/cell_pic.jpg
deleted file mode 100644
index 04e7a9c..0000000
Binary files a/sample_images/cell_pic.jpg and /dev/null differ
diff --git a/sample_images/chart.JPG b/sample_images/chart.JPG
deleted file mode 100755
index ebf13ef..0000000
Binary files a/sample_images/chart.JPG and /dev/null differ
diff --git a/sample_images/desk.JPG b/sample_images/desk.JPG
deleted file mode 100644
index f8b745c..0000000
Binary files a/sample_images/desk.JPG and /dev/null differ
diff --git a/sample_images/dollar_bill.JPG b/sample_images/dollar_bill.JPG
deleted file mode 100755
index 6d58e3b..0000000
Binary files a/sample_images/dollar_bill.JPG and /dev/null differ
diff --git a/sample_images/math_cheat_sheet.JPG b/sample_images/math_cheat_sheet.JPG
deleted file mode 100755
index a1c20e9..0000000
Binary files a/sample_images/math_cheat_sheet.JPG and /dev/null differ
diff --git a/sample_images/notepad.JPG b/sample_images/notepad.JPG
deleted file mode 100644
index afab3e2..0000000
Binary files a/sample_images/notepad.JPG and /dev/null differ
diff --git a/sample_images/receipt.jpg b/sample_images/receipt.jpg
deleted file mode 100644
index 35aa50d..0000000
Binary files a/sample_images/receipt.jpg and /dev/null differ
diff --git a/sample_images/tax.jpeg b/sample_images/tax.jpeg
deleted file mode 100644
index 99a450f..0000000
Binary files a/sample_images/tax.jpeg and /dev/null differ
diff --git a/scan.py b/scan.py
index 4aa835e..45d2b57 100644
--- a/scan.py
+++ b/scan.py
@@ -11,7 +11,6 @@
from pyimagesearch import imutils
from scipy.spatial import distance as dist
from matplotlib.patches import Polygon
-import polygon_interacter as poly_i
import numpy as np
import matplotlib.pyplot as plt
import itertools
@@ -94,7 +93,6 @@ def get_corners(self, img):
to be rescaled and Canny filtered prior to be passed in.
"""
lines = lsd(img)
-
# massages the output from LSD
# LSD operates on edges. One "line" has 2 edges, and so we need to combine the edges back into lines
# 1. separate out the lines into horizontal and vertical lines.
@@ -160,6 +158,11 @@ def get_corners(self, img):
corners = self.filter_corners(corners)
return corners
+
+
+
+
+
def is_valid_contour(self, cnt, IM_WIDTH, IM_HEIGHT):
"""Returns True if the contour satisfies all requirements set at instantitation"""
@@ -249,24 +252,11 @@ def get_contour(self, rescaled_image):
return screenCnt.reshape(4, 2)
- def interactive_get_contour(self, screenCnt, rescaled_image):
- poly = Polygon(screenCnt, animated=True, fill=False, color="yellow", linewidth=5)
- fig, ax = plt.subplots()
- ax.add_patch(poly)
- ax.set_title(('Drag the corners of the box to the corners of the document. \n'
- 'Close the window when finished.'))
- p = poly_i.PolygonInteractor(ax, poly)
- plt.imshow(rescaled_image)
- plt.show()
-
- new_points = p.get_poly_points()[:4]
- new_points = np.array([[p] for p in new_points], dtype = "int32")
- return new_points.reshape(4, 2)
-
def scan(self, image_path):
RESCALED_HEIGHT = 500.0
- OUTPUT_DIR = 'output'
+ # OUTPUT_DIR = 'output'
+ OUTPUT_DIR = 'processed_photos'
# load the image and compute the ratio of the old height
# to the new height, clone it, and resize it
@@ -287,23 +277,13 @@ def scan(self, image_path):
# apply the perspective transformation
warped = transform.four_point_transform(orig, screenCnt * ratio)
- # convert the warped image to grayscale
- gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
-
- # sharpen image
- sharpen = cv2.GaussianBlur(gray, (0,0), 3)
- sharpen = cv2.addWeighted(gray, 1.5, sharpen, -0.5, 0)
-
- # apply adaptive threshold to get black and white effect
- thresh = cv2.adaptiveThreshold(sharpen, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 15)
-
# save the transformed image
basename = os.path.basename(image_path)
- cv2.imwrite(OUTPUT_DIR + '/' + basename, thresh)
- print("Proccessed " + basename)
+ cv2.imwrite(OUTPUT_DIR + '/' + basename, warped)
+ return OUTPUT_DIR + '/' + basename
-if __name__ == "__main__":
+def main(args):
ap = argparse.ArgumentParser()
group = ap.add_mutually_exclusive_group(required=True)
group.add_argument("--images", help="Directory of images to be scanned")
@@ -311,7 +291,7 @@ def scan(self, image_path):
ap.add_argument("-i", action='store_true',
help = "Flag for manually verifying and/or setting document corners")
- args = vars(ap.parse_args())
+ args = vars(ap.parse_args(args))
im_dir = args["images"]
im_file_path = args["image"]
interactive_mode = args["i"]
@@ -324,10 +304,14 @@ def scan(self, image_path):
# Scan single image specified by command line argument --image
if im_file_path:
- scanner.scan(im_file_path)
+ return scanner.scan(im_file_path)
# Scan all valid images in directory specified by command line argument --images
else:
im_files = [f for f in os.listdir(im_dir) if get_ext(f) in valid_formats]
for im in im_files:
scanner.scan(im_dir + '/' + im)
+
+if __name__ == "__main__":
+ import sys
+ main(sys.argv[1:])
diff --git a/ui.gif b/ui.gif
deleted file mode 100644
index 8a183a8..0000000
Binary files a/ui.gif and /dev/null differ
diff --git a/utils/utils.py b/utils/utils.py
new file mode 100644
index 0000000..a961ce5
--- /dev/null
+++ b/utils/utils.py
@@ -0,0 +1,45 @@
+import requests
+import os
+import random
+import string
+import requests
+import tempfile
+from io import BytesIO
+
+
+def download_image_temp(url, image_name):
+ try:
+ # Gerar um nome aleatório para a imagem
+ image_name = image_name
+
+ # Fazer a requisição da imagem
+ response = requests.get(url, stream=True)
+ response.raise_for_status()
+
+ processed_photos_dir = "processed_photos"
+ if not os.path.exists(processed_photos_dir):
+ os.makedirs(processed_photos_dir)
+
+ # Criar um arquivo temporário
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".jpg")
+ temp_path = temp_file.name # Caminho do arquivo temporário
+
+ # Escrever a imagem no arquivo temporário
+ with open(temp_path, 'wb') as file:
+ for chunk in response.iter_content(chunk_size=8192):
+ file.write(chunk)
+
+ print(f"Imagem baixada temporariamente em {temp_path}")
+
+ return temp_path # Retorna o caminho do arquivo temporário
+
+ except requests.exceptions.HTTPError as e:
+ print(f"Erro ao baixar a imagem: {e}")
+ return None
+
+def delete_temp_file(file_path):
+ try:
+ os.remove(file_path)
+ print(f"Arquivo temporário {file_path} removido com sucesso")
+ except Exception as e:
+ print(f"Erro ao remover o arquivo temporário {file_path}: {e}")
\ No newline at end of file
diff --git a/workflow.py b/workflow.py
new file mode 100644
index 0000000..c3870e0
--- /dev/null
+++ b/workflow.py
@@ -0,0 +1,21 @@
+from connection.supabase_connection import SupabaseConnection
+import utils.utils as utils
+import scan
+import connection.patch as patch
+
+# Baixar a imagem localmente
+def workImage(photo_url, image_name, image_id):
+
+ image_path = utils.download_image_temp(photo_url, image_name)
+
+ processed_path = scan.main(["--image", f"{image_path}"])
+
+ utils.delete_temp_file(image_path)
+
+ bucket = SupabaseConnection()
+
+ data = bucket.upload_file_to_supabase(image_name, processed_path)
+
+ patch.patch(image_id, data["url"])
+
+ utils.delete_temp_file(processed_path)
\ No newline at end of file