Android Java如何绘制人物轮廓草图?求API或实现方案
如何基于人像分割结果生成人物轮廓草图?
我已经完成人物检测、人物裁剪,并用MLImageSegmentation获取到前景图,但不知道怎么生成示例图那样的人物轮廓草图,请问有没有可用的API?附上现有代码寻求解决思路:
private void createImageTransactor(Bitmap image) { MLImageSegmentationSetting setting = new MLImageSegmentationSetting.Factory().setAnalyzerType(MLImageSegmentationSetting.BODY_SEG).create(); this.analyzer = MLAnalyzerFactory.getInstance().getImageSegmentationAnalyzer(setting); if (this.isChosen(image)) { MLFrame mlFrame = new MLFrame.Creator().setBitmap(image).create(); Task<MLImageSegmentation> task = this.analyzer.asyncAnalyseFrame(mlFrame); task.addOnSuccessListener(new OnSuccessListener<MLImageSegmentation>() { @Override public void onSuccess(MLImageSegmentation mlImageSegmentationResults) { if (mlImageSegmentationResults != null) { try { cutImage = mlImageSegmentationResults.getForeground(); }catch (Exception e){ } } else { Toast.makeText(getContext() ,getResources().getString(R.string.Fail), Toast.LENGTH_SHORT).show(); } } }).addOnFailureListener(new OnFailureListener() { @Override public void onFailure(Exception e) { Toast.makeText(getContext() ,getResources().getString(R.string.Fail), Toast.LENGTH_SHORT).show(); } }); } else { Toast.makeText(getContext(), R.string.txt_not_detect_human, Toast.LENGTH_SHORT).show(); } }
目前没有直接生成这类轮廓草图的专用API,但可以基于已有的前景图通过图像处理逻辑实现,以下是两种可行思路:
思路一:借助OpenCV实现边缘检测
通过经典的Canny边缘检测算法提取前景图的轮廓,步骤如下:
- 将前景Bitmap转为OpenCV的Mat格式
- 转换为灰度图简化处理
- 运行Canny算法提取边缘
- 将结果转回Bitmap得到轮廓草图
示例代码片段(需引入OpenCV依赖):
// 前景Bitmap转Mat Mat src = new Mat(); Utils.bitmapToMat(cutImage, src); // 转灰度图 Mat grayMat = new Mat(); Imgproc.cvtColor(src, grayMat, Imgproc.COLOR_BGRA2GRAY); // Canny边缘检测 Mat edgeMat = new Mat(); Imgproc.Canny(grayMat, edgeMat, 50, 150); // 50和150为阈值,可按需调整 // 结果转回Bitmap Bitmap contourBitmap = Bitmap.createBitmap(edgeMat.cols(), edgeMat.rows(), Bitmap.Config.ARGB_8888); Utils.matToBitmap(edgeMat, contourBitmap);
思路二:基于Android原生Canvas手动提取轮廓
遍历前景图的像素,识别边缘点(即不透明像素周围存在透明像素的位置),然后在Canvas上绘制这些点形成轮廓:
// 创建空白画布用于绘制轮廓 Bitmap contourBitmap = Bitmap.createBitmap(cutImage.getWidth(), cutImage.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(contourBitmap); Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setStrokeWidth(1); int width = cutImage.getWidth(); int height = cutImage.getHeight(); // 遍历像素,识别边缘点 for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { int currentAlpha = Color.alpha(cutImage.getPixel(x, y)); // 当前像素不透明,且上下左右任意方向有透明像素,判定为边缘 if (currentAlpha == 255) { if (Color.alpha(cutImage.getPixel(x-1, y)) == 0 || Color.alpha(cutImage.getPixel(x+1, y)) == 0 || Color.alpha(cutImage.getPixel(x, y-1)) == 0 || Color.alpha(cutImage.getPixel(x, y+1)) == 0) { canvas.drawPoint(x, y, paint); } } } } // contourBitmap即为生成的轮廓草图
优化建议
- 可以对边缘结果进行模糊处理或膨胀/腐蚀操作,让轮廓线条更平滑自然
- 如果需要艺术化的手绘风格轮廓,可额外集成风格迁移类的轻量ML模型,在边缘检测结果基础上做风格转换
内容的提问来源于stack exchange,提问作者viswareddy
相关产品推荐
相关产品推荐

