Skip to content

Commit

Permalink
Merge pull request #24 from jandom/jandom/ci/setup-lint-with-isort-an…
Browse files Browse the repository at this point in the history
…d-black

ci: setup linting with isort and black
  • Loading branch information
Eric-Canas authored Jun 2, 2024
2 parents eeb9304 + c6cd428 commit 4f78bca
Show file tree
Hide file tree
Showing 8 changed files with 467 additions and 199 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Lint
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
black:
name: Run black
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x' # Specify the Python version you are using
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black isort
- name: Run black
run: |
black --check .
isort:
name: Run isort
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x' # Specify the Python version you are using
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black isort
- name: Run isort
run: |-
isort --check-only .
68 changes: 54 additions & 14 deletions documentation/benchmark/resizes.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import numpy as np
import cv2
import imageio
import numpy as np
from PIL import Image
from qreader import QReader
from pyzbar.pyzbar import decode

qreader_reader, cv2_reader, pyzbar_reader = QReader(model_size='m'), cv2.QRCodeDetector(), decode
from qreader import QReader

qreader_reader, cv2_reader, pyzbar_reader = (
QReader(model_size="m"),
cv2.QRCodeDetector(),
decode,
)


def get_scaled_sizes(start_size, end_size, step, w, h):
Expand All @@ -28,25 +33,56 @@ def draw_cross(x, y):
cv2.line(image_copy, (x + 20, y), (x, y + 20), (0, 0, 255), 2)

def draw_warn(x, y):
cv2.putText(image_copy, "!", (x + 5, y + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
cv2.putText(
image_copy,
"!",
(x + 5, y + 15),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 255, 255),
2,
)

qreader_out = qreader_reader.detect_and_decode(image=image)
cv2_out = cv2_reader.detectAndDecode(image)[0]
pyzbar_out = pyzbar_reader(image=image)

qreader_status = "YES" if len(qreader_out) > 0 and qreader_out[0] is not None else "WARN" if len(
qreader_out) > 0 else "NO"
qreader_status = (
"YES"
if len(qreader_out) > 0 and qreader_out[0] is not None
else "WARN" if len(qreader_out) > 0 else "NO"
)
cv2_status = "YES" if cv2_out != "" else "NO"
pyzbar_status = "YES" if len(pyzbar_out) > 0 else "NO"

cv2.putText(image_copy, f"Size: {current_size}", (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
cv2.putText(
image_copy,
f"Size: {current_size}",
(20, 40),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 0, 0),
2,
)

y_position = 80
x_position_text = 20
x_position_symbol = 220

for method, status in [("OpenCV", cv2_status), ("Pyzbar", pyzbar_status), ("QReader", qreader_status)]:
cv2.putText(image_copy, f"{method}:", (x_position_text, y_position), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
for method, status in [
("OpenCV", cv2_status),
("Pyzbar", pyzbar_status),
("QReader", qreader_status),
]:
cv2.putText(
image_copy,
f"{method}:",
(x_position_text, y_position),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 0, 0),
2,
)

if status == "YES":
draw_tick(x_position_symbol, y_position - 10)
Expand All @@ -61,28 +97,32 @@ def draw_warn(x, y):


def main():
image = cv2.imread('../resources/logo.png', cv2.IMREAD_GRAYSCALE)
image = cv2.imread("../resources/logo.png", cv2.IMREAD_GRAYSCALE)
h, w = image.shape

frames = []

for size in range(640, 10, -5):
size_h = size_w = size
resized_image = cv2.resize(image, (size_w, size_h), interpolation=cv2.INTER_AREA)
resized_image = cv2.resize(
image, (size_w, size_h), interpolation=cv2.INTER_AREA
)

pad_h = (640 - size_h) // 2
pad_w = (640 - size_w) // 2
resized_image = cv2.copyMakeBorder(resized_image, pad_h, pad_h, pad_w, pad_w, cv2.BORDER_CONSTANT, value=255)
resized_image = cv2.copyMakeBorder(
resized_image, pad_h, pad_h, pad_w, pad_w, cv2.BORDER_CONSTANT, value=255
)

resized_image = validate_and_write_on_image(resized_image, f"{size_w}x{size_h}")
frames.append(Image.fromarray(resized_image))

if (size_w % 50) == 0:
print(f"Done {size_w}x{size_h}")

gif_path = 'resized_image.gif'
gif_path = "resized_image.gif"
imageio.mimsave(gif_path, frames, duration=0.1)


if __name__ == '__main__':
if __name__ == "__main__":
main()
128 changes: 89 additions & 39 deletions documentation/benchmark/rotations.py
Original file line number Diff line number Diff line change
@@ -1,50 +1,59 @@
import numpy as np
import cv2
import imageio
import numpy as np
from PIL import Image
from pyzbar.pyzbar import decode

from qreader import QReader
import cv2
from pyzbar.pyzbar import decode

qreader_reader, cv2_reader, pyzbar_reader = QReader(model_size='m'), cv2.QRCodeDetector(), decode
qreader_reader, cv2_reader, pyzbar_reader = (
QReader(model_size="m"),
cv2.QRCodeDetector(),
decode,
)


def get_matrices(start_deg, end_deg, y_deg=20, w=256, h=256):
"""Yield rotation matrices for given start and end degrees, width, and height."""
# 10 degrees in radians for Y-axis rotation

rot_xs = np.linspace(np.radians(start_deg), np.radians(end_deg), end_deg - start_deg + 1)
rot_ys = np.linspace(np.radians(0), np.radians(y_deg), end_deg - start_deg +1)
rot_xs = np.linspace(
np.radians(start_deg), np.radians(end_deg), end_deg - start_deg + 1
)
rot_ys = np.linspace(np.radians(0), np.radians(y_deg), end_deg - start_deg + 1)
# Iterate on radians. Rotate on X degree by degree
for rotx, roty in zip(rot_xs, rot_ys):
focal_length = 2
cosx, sinx = np.cos(rotx), np.sin(rotx)

# X-axis rotation matrix
rotox = [
[1, 0, 0],
[0, cosx, -sinx],
[0, sinx, cosx]
]
rotox = [[1, 0, 0], [0, cosx, -sinx], [0, sinx, cosx]]
cosy, siny = np.cos(roty), np.sin(roty)

# Y-axis rotation matrix
roty = [
[cosy, 0, siny],
[0, 1, 0],
[-siny, 0, cosy]
]
roty = [[cosy, 0, siny], [0, 1, 0], [-siny, 0, cosy]]

# Combine X and Y rotation matrices
combined_roto = np.dot(rotox, roty)

pt = np.array([[-w / 2, -h / 2, 0], [w / 2, -h / 2, 0],
[w / 2, h / 2, 0], [-w / 2, h / 2, 0]], dtype=np.float32)
pt = np.array(
[
[-w / 2, -h / 2, 0],
[w / 2, -h / 2, 0],
[w / 2, h / 2, 0],
[-w / 2, h / 2, 0],
],
dtype=np.float32,
)
ptt = np.dot(pt, np.transpose(combined_roto))

# Generate input and output points
ptt[:, 0] = w / 2 + ptt[:, 0] * focal_length * h / (focal_length * h + ptt[:, 2])
ptt[:, 1] = h / 2 + ptt[:, 1] * focal_length * h / (focal_length * h + ptt[:, 2])
ptt[:, 0] = w / 2 + ptt[:, 0] * focal_length * h / (
focal_length * h + ptt[:, 2]
)
ptt[:, 1] = h / 2 + ptt[:, 1] * focal_length * h / (
focal_length * h + ptt[:, 2]
)

in_pt = np.array([[0, 0], [w, 0], [w, h], [0, h]], dtype=np.float32)
out_pt = np.array(ptt[:, :2], dtype=np.float32)
Expand All @@ -53,7 +62,6 @@ def get_matrices(start_deg, end_deg, y_deg=20, w=256, h=256):
yield transform_matrix



def validate_and_write_on_image(image, current_degs_x, current_degs_y):
def draw_tick(x, y):
# Short line (almost vertical)
Expand All @@ -67,7 +75,15 @@ def draw_cross(x, y):
cv2.line(image_copy, (x + 20, y), (x, y + 20), (0, 0, 255), 2)

def draw_warn(x, y):
cv2.putText(image_copy, "!", (x + 5, y + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2)
cv2.putText(
image_copy,
"!",
(x + 5, y + 15),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 255, 255),
2,
)

def overlay_transparent_rect(image, x, y, width, height, color, alpha):
overlay = image.copy()
Expand All @@ -83,27 +99,50 @@ def overlay_transparent_rect(image, x, y, width, height, color, alpha):
pyzbar_out = pyzbar_reader(image=image)

# Create status indicators based on decoding success
qreader_status = "YES" if len(qreader_out) > 0 and qreader_out[0] is not None else "WARN" if len(
qreader_out) > 0 else "NO"
qreader_status = (
"YES"
if len(qreader_out) > 0 and qreader_out[0] is not None
else "WARN" if len(qreader_out) > 0 else "NO"
)
cv2_status = "YES" if cv2_out != "" else "NO"
pyzbar_status = "YES" if len(pyzbar_out) > 0 else "NO"

overlay_transparent_rect(image_copy, 10, 0, 500, 40, (255, 255, 255), 0.6)
overlay_transparent_rect(image_copy, 10, 50, 250, 40*3+20, (255, 255, 255), 0.6)
overlay_transparent_rect(image_copy, 10, 50, 250, 40 * 3 + 20, (255, 255, 255), 0.6)
# Writing the degrees in the top left corner
cv2.putText(image_copy, f" x: {current_degs_x} deg - y: {round(current_degs_y, 1)} deg", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (0, 0, 0), 2)
cv2.putText(
image_copy,
f" x: {current_degs_x} deg - y: {round(current_degs_y, 1)} deg",
(10, 30),
cv2.FONT_HERSHEY_SIMPLEX,
1.25,
(0, 0, 0),
2,
)

# Status positions
y_position = 80
y_increment = 40
x_position_text = 20
x_position_symbol = 220

for method, status in [("OpenCV", cv2_status), ("Pyzbar", pyzbar_status), ("QReader", qreader_status)]:
for method, status in [
("OpenCV", cv2_status),
("Pyzbar", pyzbar_status),
("QReader", qreader_status),
]:
# Draw semi-transparent white rectangle as a background

# Draw text in black
cv2.putText(image_copy, f" {method}:", (x_position_text, y_position), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 2)
cv2.putText(
image_copy,
f" {method}:",
(x_position_text, y_position),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 0, 0),
2,
)

# Draw the symbol next to the text
if status == "YES":
Expand All @@ -118,43 +157,54 @@ def overlay_transparent_rect(image, x, y, width, height, color, alpha):
return cv2.cvtColor(image_copy, cv2.COLOR_BGR2RGB)




def main():
# Load an image (replace 'your_image_path.png' with the path to your image)
image = cv2.imread('../resources/logo.png', cv2.IMREAD_GRAYSCALE)
image = cv2.imread("../resources/logo.png", cv2.IMREAD_GRAYSCALE)
h, w = image.shape
frames = []

# Get the max transformation matrix
m = next(get_matrices(start_deg=80-1, end_deg=80, w=w, h=h))
m = next(get_matrices(start_deg=80 - 1, end_deg=80, w=w, h=h))
# Apply the perspective transformation for the corners
im_corners = cv2.perspectiveTransform(np.array([[[0, 0]], [[w, 0]], [[w, h]], [[0, h]]], dtype=np.float32), m)
im_corners = cv2.perspectiveTransform(
np.array([[[0, 0]], [[w, 0]], [[w, h]], [[0, h]]], dtype=np.float32), m
)
# Get each side pad
left_pad = abs(int(np.min(im_corners[:, :, 0])))
right_pad = int(np.max(im_corners[:, :, 0])) - w
# Apply the pads to the image
image = np.pad(image, ((10, 0), (left_pad-10, right_pad-10)), mode='constant', constant_values=255)
image = np.pad(
image,
((10, 0), (left_pad - 10, right_pad - 10)),
mode="constant",
constant_values=255,
)
h, w = image.shape
degs = 0
degs_y = 0
for matrix in get_matrices(start_deg=0, end_deg=80, y_deg=25, w=w, h=h):
# Apply the perspective transformation
transformed_image = cv2.warpPerspective(image, matrix, (w, h), flags=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT, borderValue=255)
transformed_image = cv2.warpPerspective(
image,
matrix,
(w, h),
flags=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT,
borderValue=255,
)

# Validate and write on the image
transformed_image = validate_and_write_on_image(transformed_image, degs, degs_y)
frames.append(Image.fromarray(transformed_image))
degs += 1
degs_y += 25/80
degs_y += 25 / 80
if (degs % 10) == 0:
print(f"Done {degs}º")

# Save the GIF
gif_path = 'rotated_image.gif'
gif_path = "rotated_image.gif"
imageio.mimsave(gif_path, frames, duration=0.1)


if __name__ == '__main__':
if __name__ == "__main__":
main()
Loading

0 comments on commit 4f78bca

Please sign in to comment.