使用Mask RCNN从轮廓与掩码中提取无背景目标图像咨询
需求说明
我使用Mask RCNN完成图像分类,得到了分类结果图及对应的掩码,当前输出结果如下:
我希望提取轮廓周边的目标区域,得到去除背景的单独图像,当前使用的实现代码如下:
//Display the label at the top of the bounding box int baseLine; Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); box.y = max(box.y, labelSize.height); //rectangle(frame, Point(box.x, box.y - round(1.5 * labelSize.height)), Point(box.x + round(1.5 * labelSize.width), box.y + baseLine), Scalar(255, 255, 255), FILLED); //putText(frame, label, Point(box.x, box.y), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1); // Resize the mask, threshold, color and apply it on the image Scalar color = colors[classId % colors.size()]; // Resize the mask, threshold, color and apply it on the image resize(objectMask, objectMask, Size(box.width, box.height)); Mat mask = (objectMask > maskThreshold); Mat coloredRoi = (0.3 * color + 0.7 * frame(box)); coloredRoi.convertTo(coloredRoi, CV_8UC3); // Draw the contours on the image vector<Mat> contours; Mat hierarchy; mask.convertTo(mask, CV_8U); findContours(mask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); drawContours(coloredRoi, contours, -1, color, 5, LINE_8, hierarchy, 100); coloredRoi.copyTo(frame(box), mask); imshow("img", coloredRoi); cv::waitKey(0);
单独的掩码可视化图如下:
原始输入图像如下:
请问如何调整代码,可实现提取无背景目标区域图像的需求?
解决方案
原有代码的逻辑是给目标区域叠加半透明颜色、绘制轮廓后回写到原图,没有做背景剔除,按以下方式修改即可得到无背景的目标单独图像,可根据需求选择生成纯色背景或者透明背景的结果:
方案1:生成纯色背景的目标图像
直接将掩码外的区域像素赋值为指定纯色即可,修改代码如下:
resize(objectMask, objectMask, Size(box.width, box.height)); Mat mask = (objectMask > maskThreshold); mask.convertTo(mask, CV_8U); // 掩码转为8位单通道图,目标区域值为255,背景为0 // 取原图对应 bounding box 的区域 Mat roi = frame(box).clone(); // 遍历每个像素,非目标区域设为黑色,修改为Vec3b(255,255,255)就是白色背景 for (int i = 0; i < roi.rows; i++) { for (int j = 0; j < roi.cols; j++) { if (mask.at<uchar>(i,j) == 0) { roi.at<Vec3b>(i,j) = Vec3b(0,0,0); } } } // 可选:绘制目标轮廓 vector<Mat> contours; Mat hierarchy; findContours(mask, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); drawContours(roi, contours, -1, Scalar(0,255,0), 2, LINE_8, hierarchy, 100); // 显示和保存结果 imshow("无背景目标图", roi); imwrite("output.jpg", roi); waitKey(0);
方案2:生成带透明通道的PNG图像
如果需要背景透明的效果,给图像新增alpha通道控制透明度即可,代码如下:
resize(objectMask, objectMask, Size(box.width, box.height)); Mat mask = (objectMask > maskThreshold); mask.convertTo(mask, CV_8U); Mat roi = frame(box).clone(); // 创建四通道图像(BGR+Alpha) Mat result(roi.size(), CV_8UC4); for (int i = 0; i < roi.rows; i++) { for (int j = 0; j < roi.cols; j++) { Vec3b bgr = roi.at<Vec3b>(i,j); result.at<Vec4b>(i,j) = Vec4b(bgr[0], bgr[1], bgr[2], mask.at<uchar>(i,j)); } } // 保存为PNG格式才能保留透明通道 imwrite("output_transparent.png", result);
内容的提问来源于stack exchange,提问作者Andre Ahmed
相关产品推荐
相关产品推荐

