物理の駅 by onsanai

Physics Station → PhSt 質問・疑問・間違いの指摘は、コメントに書くか、直接伝えるときっと良いことがあります。主にWindows or Ubuntu用の記事です

CCDカメラで撮像した画像をOpenCVを使って縞々模様を除去する

CCDカメラは読み出し方式による縞々模様(1行ごとに輝度の濃淡が発生する)現象が起こる。 通常、ハードウェア側で調整されるものだが、ソフトウェア側で調整する必要に迫られたので、そのコードを公開する。

なお、Visual Studio + C# + OpenCVSharp と C++を使って実装してしたので、Python版は適宜読み替えられたし。

static public Mat Deinterlacing(Mat src)
{
    Mat dst = Mat.Zeros(1, 1, MatType.CV_32FC1);
    Cv2.Reduce(src, dst, ReduceDimension.Column, ReduceTypes.Avg, MatType.CV_32FC1);

    for (int y = 0; y < dst.Rows; y++)
    {
        int ym = y - 1;
        int yp = y + 1;
        float next = 0;
        float current = dst.At<float>(y);
        if (ym < 0) { next = dst.At<float>(yp); }
        else if (yp >= dst.Rows) { next = dst.At<float>(ym); }
        else { next = (dst.At<float>(ym) + dst.At<float>(yp)) * 0.5f; }
        src[new Rect(0, y, src.Cols, 1)] *= Math.Sqrt(next / current);
    }
    return src;
}
void deinterlacing(cv::Mat& src)
{
    cv::Mat dst = cv::Mat::zeros(1, 1, CV_32FC1);
    cv::reduce(src, dst, 1, CV_REDUCE_AVG, CV_32FC1);

    for (int y = 0; y < dst.rows; y++)
    {
        int ym = y - 1;
        int yp = y + 1;
        float next = 0;
        float current = dst.at<float>(y);
        if (ym < 0) { next = dst.at<float>(yp); }
        else if (yp >= dst.rows) { next = dst.at<float>(ym); }
        else { next = (dst.at<float>(ym) + dst.at<float>(yp)) * 0.5f; }
        src(cv::Rect(0, y, src.cols, 1)) *= std::sqrt(next / current);
    }
}

検索用: インターレース解除