我正在尝试从照相机拍摄的图片中提取单个对象。存在一张没有物体的相机视图图片。相机的焦距不会改变,但是当有物体出现在视野中时,光照会发生变化。该物体是固体的,但灰度值不是恒定的。这里是右边的参考图像和左边带有物体的另一张图像的图片。这些图片都是单色的。
所有处理均在图像采集后进行,计算时间不是一个大问题。算法的精度更加重要。
我找到的大多数问题都涉及两张图片是否相似,但我想找到对象在图像中占据的区域,以进行后续测量。
到目前为止,我已经尝试了不同组合的模糊图像减法和二值化,但这不具备光照不变性。事先通过相对照明差异乘以参考图像也无法产生令人满意的结果。也许如果使用更好的模拟不同曝光的方式,它可以工作。
我还尝试了减去LoG过滤图像和一些粗糙的邻域像素比较,但都没有成功。
感觉这是一个非常直观的任务,某种描述符比较应该能够处理,但我正在努力寻找一个好的解决方案。有人知道我可能错过的好方法吗?
提前感谢您。
多亏了Franco Callari的回答,我偶然发现了直方图匹配,这让我惊讶的是OpenCV没有涵盖它的预制函数。由于这似乎是一个常见问题,我也可以在这里发布我的低效hack-up,以防有人想使用它。
所有处理均在图像采集后进行,计算时间不是一个大问题。算法的精度更加重要。
我找到的大多数问题都涉及两张图片是否相似,但我想找到对象在图像中占据的区域,以进行后续测量。
到目前为止,我已经尝试了不同组合的模糊图像减法和二值化,但这不具备光照不变性。事先通过相对照明差异乘以参考图像也无法产生令人满意的结果。也许如果使用更好的模拟不同曝光的方式,它可以工作。
我还尝试了减去LoG过滤图像和一些粗糙的邻域像素比较,但都没有成功。
感觉这是一个非常直观的任务,某种描述符比较应该能够处理,但我正在努力寻找一个好的解决方案。有人知道我可能错过的好方法吗?
提前感谢您。
多亏了Franco Callari的回答,我偶然发现了直方图匹配,这让我惊讶的是OpenCV没有涵盖它的预制函数。由于这似乎是一个常见问题,我也可以在这里发布我的低效hack-up,以防有人想使用它。
// Aligns the histogram of the source image to match that of the target image.
// Both are evaluated in a ROI, not across the whole picture.
// The function assumes 8-bit grayscale images.
static void alignHistogram(Mat alignsource, const Mat& aligntarget,
const int rowstart = 500, const int rowend = 700,
const int colstart = 0, const int colend = 1000)
{
// 1) Calculate target and source histogram in region of interest
// 2) Compute the integral of each histogram (cumulative distribution function)
// 3) Set brightness of each pixel in the source image to the brightness of the target where the CDF values are equal
Mat ROIsource = alignsource(Range(rowstart, rowend), Range(colstart, colend));
Mat ROItarget = aligntarget(Range(rowstart, rowend), Range(colstart, colend));
MatND hist_source, hist_target;
int bins = 256, int histSize[] = {bins};
float sranges[] = { 0, 256 }; const float* ranges[] = { sranges };
int channels[] = {0};
calcHist( &ROItarget, 1, channels, Mat(), hist_target, 1, histSize, ranges, true, false );
calcHist( &ROItarget, 1, channels, Mat(), hist_source, 1, histSize, ranges, true, false );
Mat CDF_target_2d, CDF_source_2d;
integral(hist_target, CDF_target_2d);
integral(hist_source, CDF_source_2d);
Mat CDF_target = CDF_target_2d.col(1), CDF_source = CDF_source_2d.col(1);
// Cycle through source image inefficiently and adjust brightness
for (int i = 0; i < alignsource.rows; i++)
{
for (int j = 0; j < alignsource.cols; j++)
{
int source_brightness = alignsource.at<unsigned char>(i, j);
double cdf_source_value = CDF_source.at<double>(source_brightness);
int target_brightness = 0;
while (target_brightness < 256) {
if (CDF_target.at<double>(target_brightness) > cdf_source_value)
break;
target_brightness++;
}
alignsource.at<unsigned char>(i, j) = target_brightness;
}
}
}
调整光线有助于获得更好的物体初步猜测,但这还不足以得到精确的轮廓,特别是当背景与物体相似或含有丰富的特征时。目前为止,我的工作就做到这里了。