カメラで撮影した写真から単一のオブジェクトを抽出しようとしています。オブジェクトのないカメラのビューの画像が存在します。カメラの焦点は変わりませんが、オブジェクトが表示されているときの照明は変わります。オブジェクトはしっかりしていますが、一定の灰色ではありません。これは、右側の参照画像と左側のオブジェクトを含む別の画像の写真です。写真はモノクロです。
すべての処理は画像取得後に行われ、計算時間は大きな問題ではありません。アルゴリズムの精度はより重要です。
ここで見つけたほとんどの質問は、2 つの写真が似ているかどうかという問題を扱っていますが、その後の測定のために、画像内でオブジェクトが占める領域を見つけることに興味があります。
これまでのところ、ぼやけた画像をしきい値で減算してから 2 値化するさまざまな組み合わせを試しましたが、これは照明不変ではありません。事前に参照画像に相対的な照明の違いを掛けても、満足のいく結果は得られません。別の露出をシミュレートするためのより良い方法が使用されれば、うまくいくかもしれません。
また、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;
}
}
}
照明を調整すると、オブジェクトの最初の推測を改善するのに役立ちますが、正確な輪郭を取得するには十分ではありません。特に、背景がオブジェクトとあまり変わらない場合や特徴が豊富な場合はそうです。一瞬。