源码
https://github.com/densen2014/Blazor100/tree/master/AI/MiOcr
点击图片区域不需要选择图片
要移除“点击图片区域选择图片”的功能,只需删除或注释掉 ImageBorder_MouseLeftButtonUp 方法及其在 XAML 中的事件绑定。
操作步骤如下:
- 删除 C# 事件处理方法
在 MainWindow.xaml.cs 中,删除如下方法:
- // 点击图片区域也可选择图片
- private void ImageBorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- SelectImageButton_Click(sender, e);
- }
复制代码
- 移除 XAML 事件绑定
在 MainWindow.xaml 中,找到绑定了 MouseLeftButtonUp="ImageBorder_MouseLeftButtonUp" 的控件(通常是 或 <img>),将该属性删除。例如:
这样,点击图片区域将不会再弹出选择图片对话框,拖放、粘贴等功能不受影响。
DrawOcrResultsOnImage 画出的区域支持鼠标右键复制文本
先上图:
要让 DrawOcrResultsOnImage 画出的区域支持鼠标右键复制文本,推荐的 WPF 实现方式如下:
- 记录每个识别区域的多边形和文本,用于命中测试。
- 在 MainImage 上监听鼠标右键事件,判断鼠标是否在某个区域内。
- 弹出右键菜单,点击“复制文本”即可将对应文本复制到剪贴板。
下面是详细实现步骤:
- 定义识别区域数据结构
在 MainWindow 类中添加:
- private List<(Geometry geometry, string text)> _ocrRegions = new();
复制代码
- 修改 DrawOcrResultsOnImage,记录区域
- private BitmapSource DrawOcrResultsOnImage(BitmapImage? image, PaddleOcrResult result)
- {
- if (image == null) return null!;
- int width = image.PixelWidth;
- int height = image.PixelHeight;
- _ocrRegions.Clear(); // 清空旧的区域
- var visual = new DrawingVisual();
- using (var dc = visual.RenderOpen())
- {
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>dc.DrawImage(image, new Rect(0, 0, width, height));
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var pen = new Pen(Brushes.Red, 2);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var typeface = new Typeface("Arial");
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>foreach (var region in result.Regions)
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var vertices = region.Rect.Points();
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var points = vertices.Select(p => new System.Windows.Point(p.X, p.Y)).ToArray();
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> // 绘制多边形
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var figure = new PathFigure(points[0], new[] { new PolyLineSegment(points.Skip(1), true) }, true);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var geometry = new PathGeometry(new[] { figure });
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> dc.DrawGeometry(null, pen, geometry);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> // 记录区域和文本
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> _ocrRegions.Add((geometry, region.Text));
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> // 绘制文字
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var formattedText = new FormattedText(
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>region.Text,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>System.Globalization.CultureInfo.CurrentCulture,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>FlowDirection.LeftToRight,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>typeface,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>20,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Brushes.Yellow,
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>1.25);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> dc.DrawText(formattedText, new System.Windows.Point(region.Rect.Center.X, region.Rect.Center.Y));
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>}
- }
- var bmp = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
- bmp.Render(visual);
- bmp.Freeze();
- return bmp;
- }
复制代码
- 监听 MainImage 的鼠标右键事件
在 MainWindow.xaml 的 增加:
- [/code][list=1]
- [*]实现右键菜单和复制逻辑
- 在 MainWindow.xaml.cs 添加:
- [/list][code]private void MainImage_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
- {
- var pos = e.GetPosition(MainImage);
- // 需要将控件坐标映射到图片像素坐标
- if (_currentImage == null || _ocrRegions.Count == 0) return;
- // 计算缩放比例和偏移
- var imgRect = new Rect(0, 0, _currentImage.PixelWidth, _currentImage.PixelHeight);
- var ctrlRect = new Rect(0, 0, MainImage.ActualWidth, MainImage.ActualHeight);
- var scale = Math.Min(ctrlRect.Width / imgRect.Width, ctrlRect.Height / imgRect.Height);
- var offsetX = (ctrlRect.Width - imgRect.Width * scale) / 2;
- var offsetY = (ctrlRect.Height - imgRect.Height * scale) / 2;
- var imgX = (pos.X - offsetX) / scale;
- var imgY = (pos.Y - offsetY) / scale;
- var imgPoint = new System.Windows.Point(imgX, imgY);
- // 命中测试
- foreach (var (geometry, text) in _ocrRegions)
- {
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>if (geometry.FillContains(imgPoint))
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> // 弹出右键菜单
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var menu = new ContextMenu();
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var item = new MenuItem { Header = "复制文本" };
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> item.Click += (s, args) => Clipboard.SetText(text);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> menu.Items.Add(item);
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> menu.IsOpen = true;
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> break;
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>}
- }
- }
复制代码 说明
• 支持图片缩放/居中情况下的坐标映射。
• 只在点击到识别区域时弹出“复制文本”菜单。
• 复制后可直接粘贴到其他地方。
如需支持多语言或批量复制,可扩展菜单项。此方案适用于 WPF,且不会影响拖放、粘贴等原有功能。
支持鼠标左键按下拖动多选区域复制文本
效果图:
你可以通过以下方式支持鼠标左键拖动框选多个 OCR 区域并复制文本:
- 鼠标左键按下时记录起点,拖动时绘制选框,松开时判断与哪些 OCR 区域相交,弹出菜单可复制所有命中的文本。
- 需要在 MainWindow 中维护选框状态,并在 MainImage 上处理相关事件。
- private System.Windows.Point? _selectStart;
- private System.Windows.Point? _selectEnd;
- private Rectangle _selectionRect = new Rectangle();
- private List<string> _selectedTexts = new();
复制代码
- XAML 增加 Canvas 覆盖层
在 MainWindow.xaml 的图片区域外包一层 Grid,并在其上放置一个 Canvas 用于绘制选框:
- <Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>
复制代码
- 鼠标事件实现
在 MainWindow.xaml.cs 添加:
- private void MainImage_MouseLeftButtonDown(object sender, MouseButtonEventArgs e){ if (_currentImage == null) return; _selectStart = e.GetPosition(MainImage); _selectEnd = null; _selectedTexts.Clear(); OverlayCanvas.Children.Clear(); MainImage.CaptureMouse();}private void MainImage_MouseMove(object sender, MouseEventArgs e){ if (_selectStart.HasValue && e.LeftButton == MouseButtonState.Pressed) {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>_selectEnd = e.GetPosition(MainImage);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>DrawSelectionRectangle(); }}private void MainImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e){ if (_selectStart.HasValue && _selectEnd.HasValue) {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var rect = GetImageRectFromControlRect(new Rect(_selectStart.Value, _selectEnd.Value));<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>_selectedTexts = _ocrRegions<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .Where(r => r.geometry.Bounds.IntersectsWith(rect))<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .Select(r => r.text)<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .ToList();<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>if (_selectedTexts.Count > 0)<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var menu = new ContextMenu();<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var item = new MenuItem { Header = $"复制所选文本({_selectedTexts.Count})" };<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> item.Click += (s, args) => Clipboard.SetText(string.Join(Environment.NewLine, _selectedTexts));<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> menu.Items.Add(item);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> menu.IsOpen = true;<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>} } _selectStart = null; _selectEnd = null; OverlayCanvas.Children.Clear(); MainImage.ReleaseMouseCapture();}private void DrawSelectionRectangle(){ OverlayCanvas.Children.Clear(); if (_selectStart.HasValue && _selectEnd.HasValue) {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var rect = new Rect(_selectStart.Value, _selectEnd.Value);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var r = new System.Windows.Shapes.Rectangle<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Stroke = Brushes.Blue,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> StrokeThickness = 2,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Fill = new SolidColorBrush(Color.FromArgb(40, 0, 0, 255)),<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Width = rect.Width,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Height = rect.Height<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>};<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Canvas.SetLeft(r, rect.Left);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Canvas.SetTop(r, rect.Top);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>OverlayCanvas.Children.Add(r); }}
复制代码
- 坐标映射辅助方法
添加一个方法,将控件坐标的选框映射到图片像素坐标:
- private Rect GetImageRectFromControlRect(Rect ctrlRect)
- {
- if (_currentImage == null) return Rect.Empty;
- var imgRect = new Rect(0, 0, _currentImage.PixelWidth, _currentImage.PixelHeight);
- var ctrlActual = new Rect(0, 0, MainImage.ActualWidth, MainImage.ActualHeight);
- var scale = Math.Min(ctrlActual.Width / imgRect.Width, ctrlActual.Height / imgRect.Height);
- var offsetX = (ctrlActual.Width - imgRect.Width * scale) / 2;
- var offsetY = (ctrlActual.Height - imgRect.Height * scale) / 2;
- // 映射到图片坐标
- double x1 = (ctrlRect.Left - offsetX) / scale;
- double y1 = (ctrlRect.Top - offsetY) / scale;
- double x2 = (ctrlRect.Right - offsetX) / scale;
- double y2 = (ctrlRect.Bottom - offsetY) / scale;
- return new Rect(new System.Windows.Point(x1, y1), new System.Windows.Point(x2, y2));
- }
复制代码
- 说明
• 支持拖动框选,松开后弹出菜单复制所有命中的文本。
• 支持图片缩放和居中。
• 右键单选依然可用。
如需高亮选中区域,可在 DrawOcrResultsOnImage 中根据 _selectedTexts 高亮对应区域。此方案适用于 WPF,且不会影响原有功能。
如何在选框内显示选中的文本内容?
图同上
在 WPF 中,如果你想在拖动选框时在选框内实时显示选中的文本内容,可以在 DrawSelectionRectangle 方法中,除了绘制矩形,还绘制文本。
实现思路如下:
- 实时获取选框内的文本
在 DrawSelectionRectangle 方法中,获取当前选框对应图片区域的文本:
- private void DrawSelectionRectangle(){ OverlayCanvas.Children.Clear(); if (_selectStart.HasValue && _selectEnd.HasValue) {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var rect = new Rect(_selectStart.Value, _selectEnd.Value);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var r = new System.Windows.Shapes.Rectangle<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Stroke = Brushes.Blue,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> StrokeThickness = 2,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Fill = new SolidColorBrush(Color.FromArgb(40, 0, 0, 255)),<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Width = rect.Width,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Height = rect.Height<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>};<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Canvas.SetLeft(r, rect.Left);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Canvas.SetTop(r, rect.Top);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>OverlayCanvas.Children.Add(r);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>// 获取选框对应图片坐标的区域<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var imgRect = GetImageRectFromControlRect(rect);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>var selectedTexts = _ocrRegions<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .Where(region => region.geometry.Bounds.IntersectsWith(imgRect))<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .Select(region => region.text)<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> .ToList();<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>if (selectedTexts.Count > 0)<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>{<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> // 在选框内绘制文本<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var text = string.Join(Environment.NewLine, selectedTexts);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> var tb = new TextBlock<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Text = text,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Foreground = Brushes.Black,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Background = new SolidColorBrush(Color.FromArgb(180, 255, 255, 255)),<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>FontSize = 16,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>TextWrapping = TextWrapping.Wrap,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Width = r.Width - 8,<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid><Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>Padding = new Thickness(4)<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> };<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Canvas.SetLeft(tb, rect.Left + 4);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> Canvas.SetTop(tb, rect.Top + 4);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid> OverlayCanvas.Children.Add(tb);<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>} }}
复制代码
- 说明
• 这样拖动时,选框内会实时显示所有被选中的文本内容。
• TextBlock 的宽度和位置做了适当缩进,避免与边框重叠。
• 若文本较多,TextWrapping 可自动换行。
- 注意事项
• 如果选框很小,文本可能显示不全,可根据需要调整字体或最小宽高。
• 若要美观,可进一步美化 TextBlock 的样式。
在执行ocr之前显示图片, 然后显示一个正在处理的提示, 提升客户体验
效果图:
你可以在执行 OCR 前先显示图片,然后在图片上方显示一个“正在处理...”的提示,OCR 完成后再隐藏提示。
推荐做法是在 XAML 中添加一个覆盖层(如 TextBlock 或 Border),通过代码控制其可见性。
- XAML 增加处理提示层
在 MainWindow.xaml 的图片区域 Grid 内,<img> 和 之后添加:
- [/code][list=1]
- [*]C# 控制提示显示/隐藏
- 在 MainWindow.xaml.cs 的 RunOcrAndDraw 前后控制提示:
- [/list][code]private async Task RunOcrAndDraw(byte[] imageBytes){ // 先显示图片 ProcessingText.Visibility = Visibility.Visible; await Task.Delay(100); // 确保UI刷新 var ocr = new PaddleOCRService(); var results = await ocr.StartOCR(imageBytes); ProcessingText.Visibility = Visibility.Collapsed; if (results.strings == null || results.strings.Count == 0) {<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>OcrTextBox.Text = "未识别到文本";<Grid>
- <Image x:Name="MainImage" Stretch="Uniform"
- MouseLeftButtonDown="MainImage_MouseLeftButtonDown"
- MouseMove="MainImage_MouseMove"
- MouseLeftButtonUp="MainImage_MouseLeftButtonUp"
- MouseRightButtonUp="MainImage_MouseRightButtonUp"/>
- <Canvas x:Name="OverlayCanvas" IsHitTestVisible="False"/>
- </Grid>return; } OcrTextBox.Text = string.Join(Environment.NewLine, results.result.Regions.Select(r => r.Text)); var drawed = DrawOcrResultsOnImage(_currentImage, results.result); MainImage.Source = drawed;}
复制代码
- 说明
• 这样图片会立即显示,提示“正在处理...”会覆盖在图片上,OCR 完成后自动隐藏。
• await Task.Delay(100); 可确保 UI 有机会刷新,防止提示未及时显示。
• 你可以根据需要调整提示样式和位置。
这样即可显著提升用户体验,避免界面卡顿或无响应的错觉。
在选框内绘制文本 出现了错误 System.ArgumentException:““-8”不是属性“Width”的有效值。”
你遇到的错误:
System.ArgumentException: “-8”不是属性“Width”的有效值。
原因是:
当选框很小时,r.Width - 8 变成了负数,TextBlock.Width 不能为负。
解决方法
在设置 TextBlock.Width 时,确保其为正数(最小为 1 或 0),可用 Math.Max:- Width = Math.Max(1, r.Width - 8),
复制代码 修正后的代码片段:- var tb = new TextBlock
- {
- Text = text,
- Foreground = Brushes.Black,
- Background = new SolidColorBrush(Color.FromArgb(180, 255, 255, 255)),
- FontSize = 16,
- TextWrapping = TextWrapping.Wrap,
- Width = Math.Max(1, r.Width - 8),
- Padding = new Thickness(4)
- };
复制代码 建议:
你也可以判断选框宽高过小时不显示文本,避免体验异常。
这样即可避免该异常,选框很小时不会再报错。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |