Plik PDF wygląda poziomo, ale wyodrębnione współrzędne są błędne: wyjaśnij wyraźnie macierz rotacji
Przeanalizuj problem niedopasowania współrzędnych obróconych stron PDF i szczegółowo wyjaśnij konwersję macierzy między przestrzenią nieobróconą a przestrzenią wyświetlania w PyMuPDF. Zawiera przykłady syntezy pamięci i listy kontrolne akceptacji wyjaśniające, jak używać OmniDoc do oceny efektów przywracania złożonego układu w procesie tłumaczenia dokumentów.
Podczas przetwarzania pliku PDF wyraźnie widziałem, że tabela znajdowała się po prawej stronie strony, ale wyodrębnione współrzędne wskazywały na lewy górny róg lub podświetlony blok kolorów spadł do pozycji nagłówka. Tego typu problem często nie jest błędem w bibliotece analizującej, ale niespójnością między układem współrzędnych pliku PDF a renderowaniem wizualnym. Ten artykuł jest przeznaczony dla programistów, którzy muszą pozycjonować tekst, dopasowywać obszary lub rysować adnotacje. Wyjaśnia, w jaki sposób atrybut /Rotate powoduje przesunięcie współrzędnych i wykorzystuje macierz rotacji PyMuPDF do zakończenia konwersji.
Wszystkie przykłady w tym artykule są syntetyzowane w pamięci i nie są odczytywane żadne rzeczywiste pliki. Przed przystąpieniem do przetwarzania ważnych dokumentów prosimy o zachowanie oryginałów, a następnie przeglądanie ich pojedynczo zgodnie z granicami i pozycjami akceptacji w dokumencie.
Co powinienem zrobić, jeśli współrzędne pliku PDF nie zgadzają się po obróceniu? Wniosek w jednym zdaniu
Użyj Page.rotation_matrix, aby przekonwertować nieobrócone współrzędne na współrzędne wyświetlane i sprawdź page.rotation strona po stronie przed przetwarzaniem. Nie zakładaj, że kierunki współrzędnych wszystkich stron są spójne.
| twoja sytuacja | Zalecane praktyki | powód |
|---|---|---|
| Wyodrębnione współrzędne tekstu nie odpowiadają pozycji wizualnej | Przed wykreśleniem pomnóż współrzędne przez Page.rotation_matrix | Domyślnie zwracane są współrzędne tekstu względem nieobróconej strony. |
| Należy zmapować pozycję kliknięcia z powrotem na oryginalne współrzędne | Do konwersji odwrotnej użyj Page.derotation_matrix | Ta macierz wykonuje odwrotną transformację ze współrzędnych wyświetlanych na współrzędne nieobrócone |
| Wymiar całkowitego przesunięcia o stałej odległości | Sprawdź CropBox i MediaBox, skompensuj za pomocą page.cropbox_position | Niespójność pomiędzy dwoma źródłami spowoduje stałe przesunięcie |
| Strony w tym samym dokumencie obracają się pod różnymi kątami | Czytaj page.rotation strona po stronie, nie multipleksuj macierzy globalnie | Stan rotacji różnych stron może być inny |
| Złożony układ (wiele kolumn, wykresy mieszane i częściowo obrócone) | Wstrzymaj proces automatyczny i przejdź do oceny ręcznej | Na takich stronach automatyczna weryfikacja może się nie powieść |
Zrozum różnicę między przestrzenią nieobróconą a przestrzenią wyświetlaną
Strony PDF mogą posiadać atrybut /Rotate o wartościach 0, 90, 180 lub 270 stopni. Ten obrót jest automatycznie stosowany podczas renderowania czytnika, ale współrzędne przepływu zawartości strony są nadal oparte na nieobróconym oryginalnym MediaBoxie. Jeśli bezpośrednio użyjesz wyodrębnionych oryginalnych współrzędnych do rysowania lub dopasowywania obszarów, wyniki będą niewyrównane.
PyMuPDF wyraźnie rozróżnia te dwa układy współrzędnych, począwszy od wersji 1.17.0:
- Nieobrócona przestrzeń: Współrzędne
Page.get_text(),Page.get_image_bbox()i wszystkich obiektów adnotacji są domyślnie zwracane względem nieobróconej strony. - Przestrzeń wyświetlacza: Tylko
Page.rectiPage.bound()będą odzwierciedlać rzeczywisty rozmiar wyświetlacza po obróceniu.
Dzięki takiemu rozwiązaniu ekstrakcja treści jest stabilna. Nawet jeśli kąt obrotu strony zostanie zmodyfikowany, współrzędne wyodrębniania tego samego tekstu nie ulegną zmianie. Jeśli jednak konieczne jest narysowanie współrzędnych z powrotem na stronę lub wyrównanie ich za pomocą interakcji wizualnych, takich jak kliknięcia myszą, należy ręcznie przeprowadzić transformację współrzędnych.
PyMuPDF udostępnia dwie kluczowe macierze:
Page.rotation_matrix: Konwertuj nieobrócone współrzędne na współrzędne wyświetlane.Page.derotation_matrix: Wykonaj operację odwrotną.
Te dwie macierze zawierają transformacje translacji i rotacji, więc programiści nie muszą ręcznie pisać obliczeń funkcji trygonometrycznych.
Przykład syntezy: Poprawne i nieprawidłowe oczekiwania dotyczące transformacji współrzędnych
Aby zademonstrować ten mechanizm, konstruujemy czysto syntetyczną scenę w pamięci, która nie opiera się na plikach zewnętrznych. Jeśli chcesz przetestować prawdziwy dokument, przygotuj wcześniej plik PDF z atrybutem /Rotate=90 i upewnij się, że jego CropBox jest zgodny z MediaBox, aby wyeliminować zakłócenia przesunięcia kadrowania.
Ustawienia wejściowe: Utwórz stronę A4 pionowo (595 x 842 pkt), ustaw /Rotate = 90. W przestrzeni nieobróconej punkt (100, 100) znajduje się w pobliżu lewego górnego rogu; po obróceniu o 90 stopni wizualna pozycja punktu zmienia się znacząco, ponieważ układ współrzędnych obraca się wraz z nim.
Oczekiwano prawidłowego wyniku: Pomnóż (100, 100) przez rotation_matrix, a wynikowe współrzędne wyświetlania powinny mieścić się w prawidłowych granicach obróconej strony (tj. page.rect). W przypadku domyślnej strony A4 obróconej o 90 stopni przeciwnie do ruchu wskazówek zegara, pierwotny lewy górny róg powinien znajdować się w pobliżu lewego dolnego rogu przestrzeni wyświetlania, czyli współrzędna x jest większa, a współrzędna y bliska 0. Konkretna wartość zależy od definicji początku MediaBoxa. Nie zakładaj po prostu, że y jest większe niż x.
Obsługa przypadków granicznych: Gdy kąt obrotu wynosi 0, rotation_matrix powinno być macierzą tożsamości. Jeśli zostanie przekazana wartość obrotu, która nie jest wielokrotnością 90 stopni, PyMuPDF zwykle ją znormalizuje, ale nadal zaleca się sprawdzenie ważności macierzy, aby uniknąć generowania współrzędnych NaN.
Python implementuje logikę weryfikacji współrzędnych
Poniższy przykład pokazuje, jak sprawdzić transformacje współrzędnych w pamięci. Pokazuje jedynie logikę operacji na macierzy i nie jest kompletnym potokiem przetwarzania plików PDF. Przed uruchomieniem upewnij się, że PyMuPDF jest zainstalowany i uruchom go w środowisku, w którym masz zablokowane zależności.
import fitz # PyMuPDF
def validate_rotation_transform():
"""合成示例:验证旋转矩阵在未旋转坐标与显示坐标间的转换"""
doc = fitz.open() # 空文档,无需文件路径
page = doc.new_page(width=595, height=842)
# 设置页面旋转90度,模拟横向显示的PDF
page.set_rotation(90)
# 定义一个在未旋转空间中的测试点 (左上角附近)
unrotated_point = fitz.Point(100, 100)
# 获取旋转矩阵并执行变换
mat = page.rotation_matrix
display_point = unrotated_point * mat
# 验证1: 变换后的点必须位于旋转后的页面可视区域内
assert page.rect.contains(display_point), (
f"变换后坐标 {display_point} 超出显示边界 {page.rect}"
)
# 验证2: 对于默认A4逆时针旋转90度,原(100,100)应变为左下角
# 即 x 接近页宽(842),y 接近 0。注意:此处纠正了常见的 y>x 误区
assert display_point.x > 500 and display_point.y < 200, (
f"90度旋转预期左下角,实际得到 ({display_point.x:.1f}, {display_point.y:.1f})"
)
# 验证3: 逆变换可精确恢复原始坐标
inv_mat = page.derotation_matrix
recovered = display_point * inv_mat
assert abs(recovered.x - unrotated_point.x) < 0.01
assert abs(recovered.y - unrotated_point.y) < 0.01
doc.close()
print("坐标变换逻辑校验通过(合成数据)")
# 请在本地环境运行,不要假设线上环境已安装fitz
validate_rotation_transform()
Ten kod nie czyta żadnego prawdziwego pliku, ale konstruuje stan strony w pamięci. Instrukcja assert sprawdza racjonalność zależności matematycznej, a nie poprawność biznesową. Jeśli rzeczywisty plik PDF zawiera niestandardowe przekształcenia MediaBox lub zagnieżdżone, może być wymagane dodatkowe debugowanie.
📊 Porównanie rdzeni
| Pozycja porównawcza | nieobrócona przestrzeń | przestrzeń wystawową |
|---|---|---|
| Typowe źródła | get_text(), get_image_bbox(), współrzędne adnotacji | Page.rect,Page.bound() |
| układ współrzędnych | Szerokość i wysokość oryginalnego MediaBoxa | Rzeczywisty rozmiar wyświetlacza po obróceniu |
| Typowe zastosowania | Ekstrakcja treści, stabilne rejestrowanie stref | Narysuj adnotacje i dopasuj je do pozycji kliknięcia |
| Metoda konwersji | Pomnóż przez rotation_matrix | Aby przywrócić, pomnóż przez derotation_matrix |
Kryteria akceptacji i granice ręcznego przeglądu
To, że kod może przekazać asercję, nie oznacza, że środowisko produkcyjne jest niezawodne. W poniższej tabeli wymieniono typowe wyjątki i decyzje dotyczące ich obsługi, aby pomóc rozróżnić scenariusze, które można zautomatyzować i wymagają ręcznej interwencji.
| Obserwuj zjawiska | Możliwe przyczyny | decyzja o przetwarzaniu |
|---|---|---|
| Wymiar całkowitego przesunięcia o stałej odległości | Początki CropBox i MediaBox są niespójne | Użyj page.cropbox_position, aby skompensować przesunięcie |
| Po obrocie współrzędne tekstu są normalne, ale obraz jest źle wyrównany. | Obraz wykorzystuje niezależną macierz transformacji CTM | Użyj get_image_rects() zamiast get_image_bbox() |
| Niektóre strony są obrócone prawidłowo, inne nieprawidłowo. | Dokument zawiera strony o różnych kątach obrotu | Sprawdź page.rotation strona po stronie, wyłącz globalną macierz pamięci podręcznej |
| Po transformacji współrzędne przekraczają granicę strony. | Sama oryginalna treść jest przycięta lub ma ujemne współrzędne | Oznacz jako nieprawidłową stronę i przenieś do ręcznego sprawdzenia |
| Strona 0 stopni nie wymaga przekształcenia, ale nadal zawiera odchylenia | Ukryte metadane rotacji zapisane przez narzędzia innych firm | Wymuś wywołanie remove_rotation() w celu zresetowania, a następnie przetworzenia |
Ta tabela dotyczy jedynie logiki transformacji współrzędnych i nie obejmuje problemów z dokładnością OCR ani kodowaniem czcionek. W przypadku skomplikowanego składu automatyczna weryfikacja może się nie powieść. Na tym etapie należy wstrzymać prace nad rurociągiem i ręcznie podjąć decyzję, czy kontynuować.
Użyj list kontrolnych do tłumaczenia dokumentów
Przed tłumaczeniem sprawdź kolejność stron, lokalizację źródła i integralność tekstu, a następnie prześlij tę samą pozbawioną czułości próbkę do procesu tłumaczenia. Po tłumaczeniu nadal musisz sprawdzić, czy tytuł, tekst i ilustracje są ze sobą zgodne, a nie tylko, czy tłumaczenie jest płynne.
OmniDoc (portal produktowy) udostępnia wieloformatowy portal do tłumaczenia dokumentów, a oficjalna strona internetowa zawiera funkcje OCR, glosariusza i porównywania dokumentów dwujęzycznych. Dla zespołów, które chcą pracować bezpośrednio z plików, jest to ścieżka warta sprawdzenia na przykładach z życia wziętych. Użyj plików pozbawionych zabezpieczeń, do przesłania których masz pozwolenie, i skorzystaj z elementów zaznaczonych w tym artykule, aby sprawdzić wyniki. Nie ma twierdzenia, że OmniDoc korzysta z bibliotek open source lub wewnętrznych algorytmów wspomnianych w tym artykule, ani też przykład nie zastępuje testowania wydajności produktu.
Dalsza lektura:
- Oficjalna dokumentacja PyMuPDF Page.rotation_matrix
- Uwaga koncepcyjna dotycząca współrzędnych PyMuPDF
🎯 Która metoda jest dla Ciebie odpowiednia?
Jeśli chcesz narysować wyodrębnione współrzędne tekstu z powrotem na stronę
Najpierw użyj rotation_matrix, aby przekonwertować na współrzędne wyświetlane, a następnie narysuj wyróżnienia lub adnotacje.
Jeśli chcesz zmapować kliknięcia myszą z powrotem na oryginalną treść
Użyj derotation_matrix do konwersji odwrotnej i sprawdź, czy punkt mieści się w prawidłowym zakresie względem page.rect.
Jeśli masz do czynienia z dokumentami o różnych kątach obrotu
Czytaj page.rotation strona po stronie, nie używaj ponownie macierzy globalnej i zaznacz strony wykraczające poza granice.
Jeśli Twoja strona zawiera złożone układy lub częściowo obrócone wykresy
Najpierw przejrzyj próbki syntetyczne i próbki rzeczywiste o małej skali, a następnie zdecyduj, czy przekazać je do automatycznego procesu. W przypadku napotkania nieprawidłowości należy je przekazać do ręcznego przeglądu.
❓ Często zadawane pytania (FAQ)
1. Dlaczego współrzędne zwracane przez get_text() są niezgodne z pozycją wizualną?
Ponieważ te interfejsy API domyślnie zwracają dane względem nieobróconej strony, podczas renderowania czytnika stosowany jest atrybut /Rotate.
2. Czy punkty odniesienia Page.rect i get_text() są takie same?
nie to samo. Page.rect i Page.bound() odzwierciedlają rozmiar obróconego wyświetlacza, podczas gdy współrzędne interfejsów API, takich jak get_text(), są zakotwiczone w oryginalnej, nieobróconej szerokości i wysokości.
3. Czy konwersja jest nadal konieczna, gdy kąt obrotu wynosi 0?
niepotrzebny. W tym momencie rotation_matrix powinna być macierzą tożsamości, ale nadal zaleca się sprawdzenie pod kątem stronniczości, ponieważ narzędzia innych firm mogą zapisywać ukryte metadane rotacji.
4. Czy po zatwierdzeniu asercji kod można wykorzystać bezpośrednio do produkcji?
Niezalecane. Twierdzenie sprawdza jedynie racjonalność zależności matematycznych. Rzeczywisty plik PDF może zawierać niestandardowy MediaBox, niezależną transformację CTM lub nieprawidłowe strony, które nadal należy przeglądać element po elemencie zgodnie z formularzem akceptacji.
📝 Podsumowanie
Źródłem niewspółosiowości współrzędnych jest różnica pomiędzy przestrzenią nieobróconą a przestrzenią wyświetlania. Używając rotation_matrix i derotation_matrix do konwersji, w połączeniu z inspekcją strona po stronie i przeglądem ręcznym, ryzyko można kontrolować w możliwym do sprawdzenia zakresie.
Wypróbuj teraz: prześlij dokument, aby rozpocząć tłumaczenie, zachowując oryginalny układ


