Drop the Zoom +/− toolbar actions; show the window through the page's uncovered corners
The wheel (and Fit, Ctrl+0) remain. The stitched page has white in areas that were never scanned; when the view rotates it to level the text, those triangles stuck out white against the dark window. The page is now shown with its exact-white pixels transparent, so the window colour shows through there instead. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+15
-9
@@ -30,12 +30,20 @@ from .ocr import Ocr, layout, paragraph_joins, reflow, text_direction
|
|||||||
IMAGE_FILTER = "Images (*.png *.jpg *.jpeg *.tif *.tiff *.bmp *.webp)"
|
IMAGE_FILTER = "Images (*.png *.jpg *.jpeg *.tif *.tiff *.bmp *.webp)"
|
||||||
|
|
||||||
|
|
||||||
def to_qimage(img):
|
def to_qimage(img, page=False):
|
||||||
"""BGR or grayscale uint8 array -> QImage (a copy)."""
|
"""BGR or grayscale uint8 array -> QImage (a copy). With `page`, exact-white pixels
|
||||||
|
(the uncovered corners of a stitched page) become transparent, so when the view
|
||||||
|
rotates the page to level it those corners show the window background through."""
|
||||||
img = np.ascontiguousarray(img)
|
img = np.ascontiguousarray(img)
|
||||||
h, w = img.shape[:2]
|
h, w = img.shape[:2]
|
||||||
fmt = QImage.Format_Grayscale8 if img.ndim == 2 else QImage.Format_BGR888
|
if not page:
|
||||||
return QImage(img.data, w, h, img.strides[0], fmt).copy()
|
fmt = QImage.Format_Grayscale8 if img.ndim == 2 else QImage.Format_BGR888
|
||||||
|
return QImage(img.data, w, h, img.strides[0], fmt).copy()
|
||||||
|
bgra = cv2.cvtColor(img, cv2.COLOR_GRAY2BGRA if img.ndim == 2 else cv2.COLOR_BGR2BGRA)
|
||||||
|
uncovered = (img == 255).all(axis=-1) if img.ndim == 3 else (img == 255)
|
||||||
|
bgra[uncovered, 3] = 0
|
||||||
|
bgra = np.ascontiguousarray(bgra)
|
||||||
|
return QImage(bgra.data, w, h, bgra.strides[0], QImage.Format_ARGB32).copy()
|
||||||
|
|
||||||
|
|
||||||
def imread(path):
|
def imread(path):
|
||||||
@@ -90,7 +98,7 @@ class Bridge(QObject):
|
|||||||
self.start_event, self.stop_event = threading.Event(), threading.Event()
|
self.start_event, self.stop_event = threading.Event(), threading.Event()
|
||||||
|
|
||||||
def publish(self, name, bgr):
|
def publish(self, name, bgr):
|
||||||
(self.frame if name == "frame" else self.page).emit(to_qimage(bgr))
|
(self.frame if name == "frame" else self.page).emit(to_qimage(bgr, page=(name == "page")))
|
||||||
|
|
||||||
def set_status(self, **kw):
|
def set_status(self, **kw):
|
||||||
self.state = {**self.state, **kw}
|
self.state = {**self.state, **kw}
|
||||||
@@ -616,8 +624,6 @@ class MainWindow(QMainWindow):
|
|||||||
self.act_boxes = act("Boxes", lambda on: self.view.show_boxes(on), "Ctrl+B", "Show recognised lines on the page", True)
|
self.act_boxes = act("Boxes", lambda on: self.view.show_boxes(on), "Ctrl+B", "Show recognised lines on the page", True)
|
||||||
self.act_boxes.setChecked(True)
|
self.act_boxes.setChecked(True)
|
||||||
act("Fit", lambda: self.view.fit(), "Ctrl+0", "Fit the page to the window")
|
act("Fit", lambda: self.view.fit(), "Ctrl+0", "Fit the page to the window")
|
||||||
act("Zoom +", lambda: self.view.zoom(1.25), QKeySequence.ZoomIn)
|
|
||||||
act("Zoom −", lambda: self.view.zoom(0.8), QKeySequence.ZoomOut)
|
|
||||||
for a in (self.act_save, self.act_copy):
|
for a in (self.act_save, self.act_copy):
|
||||||
a.setEnabled(False)
|
a.setEnabled(False)
|
||||||
|
|
||||||
@@ -735,7 +741,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.page_id += 1
|
self.page_id += 1
|
||||||
self.view.set_lines([])
|
self.view.set_lines([])
|
||||||
self.view.angle = 0.0
|
self.view.angle = 0.0
|
||||||
self.view.set_image(to_qimage(img))
|
self.view.set_image(to_qimage(img, page=True))
|
||||||
name = os.path.basename(path) if path else "page"
|
name = os.path.basename(path) if path else "page"
|
||||||
self.page_title = f"Page — {name} ({img.shape[1]}×{img.shape[0]})"
|
self.page_title = f"Page — {name} ({img.shape[1]}×{img.shape[0]})"
|
||||||
self.page_head.setText(self.page_title)
|
self.page_head.setText(self.page_title)
|
||||||
@@ -802,7 +808,7 @@ class MainWindow(QMainWindow):
|
|||||||
return
|
return
|
||||||
if flipped: # the boxes are on the page turned the right way up
|
if flipped: # the boxes are on the page turned the right way up
|
||||||
self.image = np.ascontiguousarray(self.image[::-1, ::-1])
|
self.image = np.ascontiguousarray(self.image[::-1, ::-1])
|
||||||
self.view.set_image(to_qimage(self.image))
|
self.view.set_image(to_qimage(self.image, page=True))
|
||||||
self.lines = lines
|
self.lines = lines
|
||||||
self.text, spans = layout(lines)
|
self.text, spans = layout(lines)
|
||||||
self.view.set_lines(lines, self.text, spans)
|
self.view.set_lines(lines, self.text, spans)
|
||||||
|
|||||||
Reference in New Issue
Block a user