.NET MAUI中如何在相机视图绘制矩形并裁剪身份证区域?
实现相机视图居中矩形框选并裁剪身份证的方案
跨平台可行方案(基于.NET MAUI)
因为Xamarin Forms已被.NET MAUI替代,推荐使用官方支持的组件组合实现:
- MediaElement:用于相机预览显示
- SkiaSharp:用于在预览上层绘制居中矩形,同时处理图像裁剪
步骤与代码示例
- 安装依赖包:
Microsoft.Maui.Controls.MediaElement和SkiaSharp.Views.Maui - XAML布局(叠加相机预览与绘图画布):
<Grid> <MediaElement x:Name="CameraPreview" Source="Camera" IsPlaying="True" /> <skia:SKCanvasView x:Name="OverlayCanvas" PaintSurface="OverlayCanvas_PaintSurface" /> <Button Text="拍照裁剪" Clicked="CaptureAndCrop_Clicked" HorizontalOptions="Center" VerticalOptions="End" Margin="0,0,0,20" /> </Grid>
- C#逻辑处理:
// 绘制居中身份证框 private void OverlayCanvas_PaintSurface(object sender, SkiaSharp.Views.Maui.SKPaintSurfaceEventArgs e) { var canvas = e.Surface.Canvas; canvas.Clear(); var previewWidth = CameraPreview.Width; var previewHeight = CameraPreview.Height; if (previewWidth == 0 || previewHeight == 0) return; // 身份证标准比例 85.6mm/54mm ≈1.585 const double idCardRatio = 85.6 / 54; float rectWidth, rectHeight; // 根据预览尺寸适配矩形大小,保持居中 if (previewWidth / previewHeight > idCardRatio) { rectHeight = (float)previewHeight * 0.8f; rectWidth = (float)(rectHeight * idCardRatio); } else { rectWidth = (float)previewWidth * 0.8f; rectHeight = (float)(rectWidth / idCardRatio); } float x = (float)(previewWidth - rectWidth) / 2; float y = (float)(previewHeight - rectHeight) / 2; // 绘制红色边框 using var paint = new SkiaSharp.SKPaint { Color = SkiaSharp.SKColors.Red, Style = SkiaSharp.SKPaintStyle.Stroke, StrokeWidth = 4, IsAntialias = true }; canvas.DrawRect(x, y, rectWidth, rectHeight, paint); } // 拍照并裁剪图像 private async void CaptureAndCrop_Clicked(object sender, EventArgs e) { var capturedImage = await CameraPreview.CapturePhotoAsync(); if (capturedImage == null) return; // 解码捕获的图像 using var bitmap = SkiaSharp.SKBitmap.Decode(capturedImage.FullPath); var imageWidth = bitmap.Width; var imageHeight = bitmap.Height; // 计算裁剪区域(与预览框比例一致) const double idCardRatio = 85.6 / 54; int cropWidth, cropHeight; if (imageWidth / imageHeight > idCardRatio) { cropHeight = (int)(imageHeight * 0.8f); cropWidth = (int)(cropHeight * idCardRatio); } else { cropWidth = (int)(imageWidth * 0.8f); cropHeight = (int)(cropWidth / idCardRatio); } int x = (imageWidth - cropWidth) / 2; int y = (imageHeight - cropHeight) / 2; // 执行裁剪 using var croppedBitmap = bitmap.Subset(new SkiaSharp.SKRectI(x, y, x + cropWidth, y + cropHeight)); // 输出裁剪后的图像(示例:转成流存储或显示) using var imageStream = new MemoryStream(); croppedBitmap.Encode(SkiaSharp.SKEncodedImageFormat.Jpeg, 90).SaveTo(imageStream); imageStream.Position = 0; // 后续处理逻辑... }
平台原生替代方案
如果需要更精细的控制,可使用平台原生API:
- Android:采用
CameraX实现预览,自定义SurfaceView叠加绘制矩形,通过ImageCapture获取图像后裁剪 - iOS:基于
AVFoundation创建预览层,添加CAShapeLayer绘制矩形,捕获图像后用CoreGraphics裁剪
注意事项
- 需在项目中配置相机、存储权限(AndroidManifest.xml/Info.plist)
- 可调整代码中
0.8f的缩放系数,让矩形更贴合实际身份证大小 - 若相机预览与捕获图像比例不一致,需额外做坐标映射(上述示例已按比例适配,可满足大部分场景)
内容的提问来源于stack exchange,提问作者Omar Cravioto
相关产品推荐
相关产品推荐

