Skip to content

Commit

Permalink
Merge pull request #256 from sbrunner/fix_angles
Browse files Browse the repository at this point in the history
Fix angles
  • Loading branch information
sbrunner authored Aug 28, 2022
2 parents 460000c + febccb4 commit 1dc4ada
Show file tree
Hide file tree
Showing 36 changed files with 48 additions and 37 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
python-version:
- '3.8'
- '3.9'
- '3.10'

steps:
- name: GitHub event
Expand Down
69 changes: 43 additions & 26 deletions deskew/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,37 @@ def determine_skew_debug_images(
angle_pm_90=angle_pm_90,
)
hough_line_data, hough_line_peaks_data, all_freqs = data
freqs_original, freqs = all_freqs
freqs0, freqs = all_freqs

skew_angle2 = None if skew_angle is None else (skew_angle + np.pi / 2) % (np.pi) - np.pi / 2
booth_angle: List[float] = []
skew_angles0: List[float] = []
if skew_angle is not None:
skew_angle0: float = float(skew_angle % np.pi - np.pi / 2)
booth_angle = [float(skew_angle), skew_angle0]
skew_angles0 = [skew_angle0] if angle_pm_90 else booth_angle

limits = []
limits: List[Tuple[float, float]] = []
limits2: List[Tuple[float, float]] = []
if min_angle is not None and max_angle is not None:
min_angle_norm = min_angle % (np.pi / (1 if angle_pm_90 else 2))
max_angle_norm = max_angle % (np.pi / (1 if angle_pm_90 else 2))
if min_angle_norm < max_angle_norm:
min_angle_norm += np.pi / (1 if angle_pm_90 else 2)
for add in [0.0] if angle_pm_90 else [0.0, np.pi / 2]:
min_angle_limit = (min_angle_norm + add + np.pi / 2) % np.pi - np.pi / 2
max_angle_limit = (max_angle_norm + add + np.pi / 2) % np.pi - np.pi / 2
min_angle_limit: float = (min_angle_norm + add + np.pi / 2) % np.pi - np.pi / 2
max_angle_limit: float = (max_angle_norm + add + np.pi / 2) % np.pi - np.pi / 2
min_angle_limit2: float = min_angle_limit % np.pi - np.pi / 2
max_angle_limit2: float = max_angle_limit % np.pi - np.pi / 2
if min_angle_limit < max_angle_limit:
limits.append((-np.pi / 2, min_angle_limit))
limits.append((max_angle_limit, np.pi / 2))
else:
limits.append((max_angle_limit, min_angle_limit))
if min_angle_limit2 < max_angle_limit2:
limits2.append((-np.pi / 2, min_angle_limit2))
limits2.append((max_angle_limit2, np.pi / 2))
else:
limits2.append((max_angle_limit2, min_angle_limit2))

debug_images = []

Expand All @@ -160,14 +173,10 @@ def determine_skew_debug_images(
axe.set_title("Hough transform")
axe.set_xlabel("Angles (degrees)")
axe.set_ylabel("Distance (pixels)")
if skew_angle is not None:
axe.axline((np.rad2deg(skew_angle), 0), (np.rad2deg(skew_angle), 10), color="lightgreen")
if not angle_pm_90:
if TYPE_CHECKING:
assert skew_angle2 is not None # nosec
axe.axline((np.rad2deg(skew_angle2), 0), (np.rad2deg(skew_angle2), 10), color="lightgreen")
for angle in skew_angles0:
axe.axline((np.rad2deg(angle), 0), (np.rad2deg(angle), 10), color="lightgreen")

for limit_min, limit_max in limits:
for limit_min, limit_max in limits2:
if limit_min != -np.pi / 2:
axe.axline((np.rad2deg(limit_min), 0), (np.rad2deg(limit_min), 10))
if limit_max != np.pi / 2:
Expand Down Expand Up @@ -211,21 +220,25 @@ def determine_skew_debug_images(
axe.set_axis_off()
axe.set_title("Detected lines")

for _, angle, dist in zip(*hough_line_peaks_data):
(coord0x, coord0y) = dist * np.array([np.cos(angle), np.sin(angle)])
for _, line_angle, dist in zip(*hough_line_peaks_data):
(coord0x, coord0y) = dist * np.array([np.cos(line_angle), np.sin(line_angle)])
angle2 = (
(angle % np.pi - np.pi / 2) if angle_pm_90 else ((angle + np.pi / 4) % (np.pi / 2) - np.pi / 4)
(line_angle % np.pi - np.pi / 2)
if angle_pm_90
else ((line_angle + np.pi / 4) % (np.pi / 2) - np.pi / 4)
)
diff = float(abs(angle2 - skew_angle)) if skew_angle is not None else 999.0
if diff < 0.001:
axe.axline((coord0x, coord0y), slope=np.tan(angle + np.pi / 2), linewidth=1, color="lightgreen")
axe.axline(
(coord0x, coord0y), slope=np.tan(line_angle + np.pi / 2), linewidth=1, color="lightgreen"
)
else:
axe.axline((coord0x, coord0y), slope=np.tan(angle + np.pi / 2), linewidth=1)
axe.axline((coord0x, coord0y), slope=np.tan(line_angle + np.pi / 2), linewidth=1)
axe.text(
coord0x,
coord0y,
f"{round(np.rad2deg(angle)*1000)/1000}",
rotation=np.rad2deg(angle - np.pi / 2),
f"{round(np.rad2deg(line_angle)*1000)/1000}",
rotation=np.rad2deg(line_angle - np.pi / 2),
rotation_mode="anchor",
transform_rotates_text=True,
)
Expand All @@ -245,7 +258,13 @@ def determine_skew_debug_images(
axe[0].set_title("Original detected angles")
axe[1].set_title("Corrected angles")

def fill_polar(axe: Any, freqs: Dict[np.float64, int], half: bool = False) -> None:
def fill_polar(
axe: Any,
freqs: Dict[np.float64, int],
angles: List[float],
limits: List[Tuple[float, float]],
half: bool = False,
) -> None:
axe.scatter(freqs.keys(), freqs.values())
axe.set_theta_zero_location("N")
axe.grid(True)
Expand All @@ -256,19 +275,17 @@ def fill_polar(axe: Any, freqs: Dict[np.float64, int], half: bool = False) -> No
axe.set_thetamin(-90)
axe.set_thetamax(90)

if skew_angle is not None:
axe.axvline(skew_angle, color="lightgreen")
if not angle_pm_90 or not half:
axe.axvline(skew_angle2, color="lightgreen")
for angle in angles:
axe.axvline(angle, color="lightgreen")

for limit_min, limit_max in limits:
if limit_min != -np.pi / 2 and (not half or -np.pi / 4 < limit_min < np.pi / 4):
axe.axvline(limit_min)
if limit_max != np.pi / 2 and (not half or -np.pi / 4 < limit_max < np.pi / 4):
axe.axvline(limit_max)

fill_polar(axe[0], freqs_original)
fill_polar(axe[1], freqs, not angle_pm_90)
fill_polar(axe[0], freqs0, skew_angles0, limits2)
fill_polar(axe[1], freqs, [] if skew_angle is None else [float(skew_angle)], limits, not angle_pm_90)

plt.tight_layout()
with tempfile.NamedTemporaryFile(suffix=".png") as file:
Expand Down
Binary file modified tests/debug-images-detected_lines-90-many-peaks.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-90-min-max.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-90.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-many-peaks.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-min-max-inverted.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-min-max-negative.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-min-max-positive.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines-min-max.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-detected_lines.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform-90-many-peaks.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform-90-min-max.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform-90.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform-many-peaks.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform-min-max.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-hough_transform.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-polar_angles-90-many-peaks.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-polar_angles-90-min-max-inverted.expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/debug-images-polar_angles-90-min-max.expected.png
Binary file modified tests/debug-images-polar_angles-90.expected.png
Binary file modified tests/debug-images-polar_angles-many-peaks.expected.png
Binary file modified tests/debug-images-polar_angles-min-max-inverted.expected.png
Binary file modified tests/debug-images-polar_angles-min-max-negative.expected.png
Binary file modified tests/debug-images-polar_angles-min-max-positive.expected.png
Binary file modified tests/debug-images-polar_angles-min-max.expected.png
Binary file modified tests/debug-images-polar_angles.expected.png
15 changes: 4 additions & 11 deletions tests/test_deskew.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
NpNdarrayInt = np.ndarray


def check_image(root_folder, image, name, level=0.9):
def check_image(root_folder, image, name, level=1.0):
assert image is not None, "Image required"
expected_name = os.path.join(os.path.dirname(__file__), f"{name}.expected.png")
result_name = os.path.join(root_folder, f"{name}.result.png")
Expand All @@ -34,23 +34,16 @@ def check_image(root_folder, image, name, level=0.9):
if diff is None:
cv2.imwrite(result_name, image)
assert diff is not None, "No diff generated"
if score > level:
if score < level:
cv2.imwrite(result_name, image)
cv2.imwrite(diff_name, diff)
assert score > level, f"{result_name} != {expected_name} => {diff_name} ({score} > {level})"
assert score >= level, f"{result_name} != {expected_name} => {diff_name} ({score} < {level})"


def image_diff(image1: NpNdarrayInt, image2: NpNdarrayInt) -> Tuple[float, NpNdarrayInt]:
"""Do a diff between images."""
width = max(image1.shape[1], image2.shape[1])
height = max(image1.shape[0], image2.shape[0])
image1 = cv2.resize(image1, (width, height))
image2 = cv2.resize(image2, (width, height))

image1 = image1 if len(image1.shape) == 2 else cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
image2 = image2 if len(image2.shape) == 2 else cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

score, diff = structural_similarity(image1, image2, full=True)
score, diff = structural_similarity(image1, image2, multichannel=True, full=True)
diff = (255 - diff * 255).astype("uint8")
return score, diff

Expand Down

0 comments on commit 1dc4ada

Please sign in to comment.