如何在Roboflow与Jetpack Compose中对齐漫画气泡检测矩形?
解决Jetpack Compose Canvas绘制漫画气泡矩形对齐问题
我正在实现漫画气泡检测功能:先截取设备屏幕,接收API返回的检测结果,再用Jetpack Compose的Canvas绘制矩形,但矩形始终无法和气泡正确对齐。
我的代码:
@Composable internal fun ScreenShotDrawSpeech( bubbleDomain: BubbleDomain, modifier: Modifier = Modifier, ) { Canvas( modifier = modifier .fillMaxSize() .background(background_overlay), onDraw = { bubbleDomain.predictions.forEach { prediction -> val left = prediction.x val top = prediction.y drawRect( color = Color.Red, topLeft = Offset(left.toFloat(), top.toFloat()), size = Size(prediction.width.toFloat(), prediction.height.toFloat()), style = Stroke(width = 2f), ) } }, ) }
效果截图:
问题核心
坐标系统不匹配:API返回的x/y/width/height是原始截图的像素坐标,而Compose Canvas的坐标基于当前布局的显示尺寸(经过设备密度缩放后的像素),两者尺寸比例不一致,直接使用原始坐标会导致错位。
解决方法
通过坐标缩放转换,将API返回的原始像素坐标适配到Canvas的显示坐标系中:
- 传递原始截图的真实像素尺寸到Composable
- 计算Canvas与原始截图的缩放比例,可选保持等比例避免变形
- 转换所有预测坐标和宽高后再绘制
修改后的代码:
@Composable internal fun ScreenShotDrawSpeech( bubbleDomain: BubbleDomain, originalScreenshotSize: Size, // 原始截图的像素尺寸:width=截图宽,height=截图高 modifier: Modifier = Modifier, ) { Canvas( modifier = modifier .fillMaxSize() .background(background_overlay), onDraw = { // 获取当前Canvas的实际显示尺寸 val canvasWidth = size.width val canvasHeight = size.height // 计算等比例缩放系数(避免拉伸变形) val scaleX = canvasWidth / originalScreenshotSize.width val scaleY = canvasHeight / originalScreenshotSize.height val scale = min(scaleX, scaleY) // 计算居中偏移量(等比例缩放后留白的居中补偿) val offsetX = (canvasWidth - originalScreenshotSize.width * scale) / 2 val offsetY = (canvasHeight - originalScreenshotSize.height * scale) / 2 bubbleDomain.predictions.forEach { prediction -> // 转换原始坐标到Canvas坐标系 val left = prediction.x.toFloat() * scale + offsetX val top = prediction.y.toFloat() * scale + offsetY val width = prediction.width.toFloat() * scale val height = prediction.height.toFloat() * scale drawRect( color = Color.Red, topLeft = Offset(left, top), size = Size(width, height), style = Stroke(width = 2f), ) } }, ) }
额外说明
- 如果允许截图拉伸填充Canvas,可直接用
scaleX和scaleY分别缩放,不需要取最小值和计算偏移 - 确保
originalScreenshotSize是截图的真实像素尺寸(比如截图Bitmap的宽高) - 若API返回的坐标原点不是左上角,需额外做坐标方向转换
内容的提问来源于stack exchange,提问作者OliverDamon
相关产品推荐
相关产品推荐

