我正在尝试从相机拍摄的照片中提取单个对象。存在没有对象的相机视图的图片。相机的焦点不会改变,但是当物体在视野中时,光照会改变。该物体是实心的,但不是恒定的灰色阴影。这是右侧参考图像的图片和左侧带有对象的另一张图像。图片是单色的。
所有的处理都是在图像采集和计算时间之后发生的,这不是一个大问题。算法的精度更重要。
我在这里找到的大多数问题都涉及两张图片是否相似的问题,但我有兴趣找到对象在图像中占据的区域以进行后续测量。
到目前为止,我已经尝试过用阈值对模糊图像进行减法然后二值化的不同组合,但这并不是光照不变的。预先将参考图像乘以相对照明差异也不会产生令人满意的结果。如果使用更好的方法来模拟不同的曝光,也许它会起作用。
我还尝试减去 LoG 过滤图像和一些粗略的邻域像素比较,但没有成功。
感觉像是一个非常直观的任务,某种描述符比较应该能够处理,但我正在努力寻找一个好的解决方案。有谁知道我一直失踪的好方法?
提前致谢。
感谢 Franco Callari 的回答,我偶然发现了直方图匹配,令我惊讶的是,现成的 OpenCV 函数并未涵盖该匹配。由于这似乎是一个常见问题,我不妨在这里发布我的低效破解,以防有人想使用它。
// 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;
}
}
}
调整照明有助于更好地初步猜测物体,但不足以获得精确的轮廓,尤其是在背景与物体差别不大或特征丰富的情况下。就我所知片刻。