在 OpenCV 中去除噪声以创建掩码
Noise removal to create mask in OpenCV
我需要创建一个遮罩来根据两张相关图像检索对象(前景对象)。
图片 1:
[![在此处输入图片描述]
图 2:
[![在此处输入图片描述]
图像包含前景对象和带纹理的背景。
这两张图片除了image2中的前景对象可能发生了一点变化(它可能已经旋转,平移or/and缩放)之外大部分是相同的。
使用 OpenCV,我执行了以下操作:
- 执行图像对齐(使用
findTransformECC
和参数 cv::MOTION_AFFINE
)以获得前景的变换;
- 根据上面的变换矩阵对image1进行变换(使用
cv::warpAffine
和参数cv::INTER_LINEAR
+ cv::WARP_INVERSE_MAP
);
- 在 image2 和已经转换的 image1 之间做绝对差异(
cv::absdiff
& cv::threshold
with param cv::THRESH_BINARY_INV
)。
我想我已经接近我的目标了,但由于背景区域残留的噪音,我仍然无法获得干净的前景物体蒙版。
消除 image_absdiff_invert.png(上图)上的所有噪声以创建前景对象的干净蒙版的解决方案是什么?
刚刚试过了
使用形态学操作通常有点棘手(反复试验)并给了我这个结果:
虽然使用中值滤波器可能是一个很好的预处理(或者甚至可能足以进行轮廓提取)并给出这个结果(这只是输入图像的中值模糊,还没有形态学操作):
这里是测试代码:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/maskNoise.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat mask = input.clone();
cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
//cv::erode(mask, mask, cv::Mat());
//cv::erode(mask, mask, cv::Mat());
//cv::dilate(mask, mask, cv::Mat());
//cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::Mat median;
cv::medianBlur(input, median, 7);
cv::Mat resizedIn;
cv::Mat resizedMask;
cv::Mat resizedMedian;
cv::resize(mask, resizedMask, cv::Size(), 0.5, 0.5);
cv::resize(median, resizedMedian, cv::Size(), 0.5, 0.5);
cv::resize(input, resizedIn, cv::Size(), 0.5, 0.5);
cv::imshow("input", resizedIn);
cv::imshow("mask", resizedMask);
cv::imshow("median", resizedMedian);
cv::imwrite("C:/Whosebug/Output/maskNoiseMorph.png", mask);
cv::imwrite("C:/Whosebug/Output/maskNoiseMedian.png", median);
cv::waitKey(0);
return 0;
}
我需要创建一个遮罩来根据两张相关图像检索对象(前景对象)。
图片 1:
[![在此处输入图片描述]
图 2:
[![在此处输入图片描述]
图像包含前景对象和带纹理的背景。 这两张图片除了image2中的前景对象可能发生了一点变化(它可能已经旋转,平移or/and缩放)之外大部分是相同的。
使用 OpenCV,我执行了以下操作:
- 执行图像对齐(使用
findTransformECC
和参数cv::MOTION_AFFINE
)以获得前景的变换; - 根据上面的变换矩阵对image1进行变换(使用
cv::warpAffine
和参数cv::INTER_LINEAR
+cv::WARP_INVERSE_MAP
); - 在 image2 和已经转换的 image1 之间做绝对差异(
cv::absdiff
&cv::threshold
with paramcv::THRESH_BINARY_INV
)。
我想我已经接近我的目标了,但由于背景区域残留的噪音,我仍然无法获得干净的前景物体蒙版。
消除 image_absdiff_invert.png(上图)上的所有噪声以创建前景对象的干净蒙版的解决方案是什么?
刚刚试过了
使用形态学操作通常有点棘手(反复试验)并给了我这个结果:
虽然使用中值滤波器可能是一个很好的预处理(或者甚至可能足以进行轮廓提取)并给出这个结果(这只是输入图像的中值模糊,还没有形态学操作):
这里是测试代码:
int main(int argc, char* argv[])
{
cv::Mat input = cv::imread("C:/Whosebug/Input/maskNoise.png", CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat mask = input.clone();
cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
cv::erode(mask, mask, cv::Mat());
//cv::erode(mask, mask, cv::Mat());
//cv::erode(mask, mask, cv::Mat());
//cv::dilate(mask, mask, cv::Mat());
//cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::dilate(mask, mask, cv::Mat());
cv::Mat median;
cv::medianBlur(input, median, 7);
cv::Mat resizedIn;
cv::Mat resizedMask;
cv::Mat resizedMedian;
cv::resize(mask, resizedMask, cv::Size(), 0.5, 0.5);
cv::resize(median, resizedMedian, cv::Size(), 0.5, 0.5);
cv::resize(input, resizedIn, cv::Size(), 0.5, 0.5);
cv::imshow("input", resizedIn);
cv::imshow("mask", resizedMask);
cv::imshow("median", resizedMedian);
cv::imwrite("C:/Whosebug/Output/maskNoiseMorph.png", mask);
cv::imwrite("C:/Whosebug/Output/maskNoiseMedian.png", median);
cv::waitKey(0);
return 0;
}