【화상 처리 100개 노크에 도전】Q.23. 히스토그램 평탄화

15831 단어 C++이미지 처리

사용한 라이브러리



【화상 처리 100개 노크】 독자적인 화상 입출력 클래스를 만든다

Q.23. 히스토그램 평탄화



히스토그램 평탄화를 구현하라.
히스토그램 평탄화는 히스토그램을 평탄하게 변경하는 조작이며, 상기 평균값이나 표준 편차 등을 필요로하지 않고 히스토그램 값을 평형화하는 조작이다.

픽셀값 $z\to z'$의 변환은
z' = \frac{z_{\rm max}}{S} \sum_{i=0}^z h(i)

에서 주어진 것 같습니다. 뭐야 이 식.

식의 의미를 생각해 보자.



식을 조금 다시 작성해 봅니다. $\sum_{i=0}^z h(i)/S$는 누적 분포 함수이므로
\sum_{i=0}^z h(i)/S \equiv p(z)

로 정의합니다. 그러면 히스토그램 평탄화의 공식은
z' = z_{\rm max}p(z)

라고 쓸 수 있습니다. 누적 분포 함수로부터 접근하는 것이 전망이 좋을 것 같습니다.

목표는 히스토그램을 평탄화하는 것이 었습니다. 완전히 평평한 히스토그램의 경우 누적 분포 함수는 $z/z_{\rm max}$입니다. 그래서 $z$를 잘 변환하여 이상에 접근하는 것을 생각합니다.

여기서 이미지를 잡기 위해 $f(x)=x^2$의 선형화를 생각합니다. 이를 위해 $f(x)=X$ 되는 변수 $X$를 생각해 보자. 이러한 변수 변환을 하면 선형화가 가능합니다.

누적 분포 함수 $p(z)$ 의 이야기로 돌아갑니다. $p(z)$ 는 일반적으로 선형이 아니지만, 앞의 예를 따릅니다.
p(z) \equiv z'/z_{\rm max}

를 만족하는 변수 $z'$를 고려하십시오. 이것은 원래의 표현 자체입니다. 이산 변수이므로 엄밀한 평탄화는 일반적으로는 할 수 없지만, 그런데 어느 정도 효과가 있는지 살펴보겠습니다.
int main()
{
    PPM ppm("imori.pnm");
    int width = ppm.Get_width();
    int height = ppm.Get_height();

    int N = 256;
    std::vector<int> hist(N);
    std::vector<double> p(N);
    for (int n = 0; n < N; n++)
    {
        hist[n] = 0;
        p[n] = 0;
    }

    for (int j = 0; j < height; j++)
        for (int i = 0; i < width; i++)
        {
            hist[ppm(i, j, 'r')]++;
            hist[ppm(i, j, 'g')]++;
            hist[ppm(i, j, 'b')]++;
        }

    for (int n = 0; n < N; n++)
        for(int m=0; m<n+1; m++)
        {
                p[n] += hist[m]/(double)(3.*width*height);
        }
    std::ofstream ofs("p0.txt");
    for (int n = 0; n < N; n++)
    {
        ofs << p[n] << std::endl;
    }
    int zmax = 255;

    PPM ppm2(width, height);
    for (int j = 0; j < height; j++)
        for (int i = 0; i < width; i++)
        {
            ppm2(i, j, 'r') = zmax * p[ppm(i, j, 'r')];
            ppm2(i, j, 'g') = zmax * p[ppm(i, j, 'g')];
            ppm2(i, j, 'b') = zmax * p[ppm(i, j, 'b')];

        }
    for (int n = 0; n < N; n++)
    {
        hist[n] = 0;
        p[n] = 0;
    }
    for (int j = 0; j < height; j++)
        for (int i = 0; i < width; i++)
        {
            hist[ppm2(i, j, 'r')]++;
            hist[ppm2(i, j, 'g')]++;
            hist[ppm2(i, j, 'b')]++;
        }

    for (int n = 0; n < N; n++)
        for (int m = 0; m < n + 1; m++)
        {
            p[n] += hist[m] / (double)(3. * width * height);
        }
    ppm2.Flush("out.ppm");

    std::ofstream ofs2("p.txt");
    for (int n = 0; n < N; n++)
    {
        ofs2 << p[n] << std::endl;
    }




    return 0;
}



누적 분포 함수는

오! 생각보다 평평하게!

좋은 웹페이지 즐겨찾기