1. 程式人生 > >OPENCV影象處理提高(一)影象增強

OPENCV影象處理提高(一)影象增強

在影象處理學習中會涉及到直方圖,直方圖很好地表現了影象的灰度資訊;同時我們注意到在暗影象中,直方圖的分量集中在灰度級的低端;亮影象的灰度值集中在直方圖灰度值的高階;低對比度的影象有較窄的直方圖,並集中於直方圖的中間部分;高對比度的影象中直方圖的分量覆蓋很寬的範圍,而且畫素的分佈沒有太不均勻,只能看到少量垂線比其他高許多。通過影象增強可以有效地減弱這些缺陷
人真皮成纖維細胞

                            圖 1

人臉

                           圖   2

如圖1,細胞表面的一些地方較為模糊,圖2,整體圖片偏亮
來看先來看第一張圖的直方分佈圖:
這裡寫圖片描述


分量集中在灰度值較高地地方。
第二張圖的直方分佈圖:
這裡寫圖片描述
直方圖

來看一下兩張圖片的直方分佈圖片:

下面兩張是經影象增強處理圖片:
處理後的細胞圖片

                              圖 3

可以明顯看到圖片比之前的要清晰;
再來看其直方分佈圖:
這裡寫圖片描述

處理後的人像
圖 4
人臉的直方分佈圖:
這裡寫圖片描述
首先,我們設連續的灰度r和z,同時令Pr(r)Pz(z)表示其連續的概率密度函式。

Pr(r)為原來影象的灰度概率函式,P
z
(z)
為經處理後的概率函式:
同時我們設一個隨機變數s:
s=T(r)=(L1)r0Pr(w)dw
其中w為積分變數;
接著定義隨機變數z:
G(z)=(L1)z0Pz(t)dt=s
其中t為積分變數;
由這兩個公式可得G(z)=T(r)
z=G1[T(r)]=G1(s)
當輸入函式Pr(r)時,變換函式T(r)可得到s;同時,Pz(z)可經過G(z)變換得到s,同時得到
z=G1[T(r)]=G1[(L1)r0Pr(w)dw]
在實際中影象的直方圖灰度分量是離散的,處理離散量時,只求得到一個近似的直方圖:
s
k
=T(rk)=(L1)kj=0Pr(rj)=L1MNkj=0nj,k=0,1,2,3,,L
1

其中MN是影象總的畫素點,nj是具有灰度值rj的畫素的個數,L是影象中可能的灰度級數;
接下來上程式碼:
#include<opencv2\opencv.hpp>
#include<opencv\cv.h>
#include<opencv2\core\core.hpp>
#include<stdlib.h>
#include<math.h>

using namespace cv;
using namespace std;

void  enhance(Mat src, Mat dir)
{    
    FILE *fp;
    fp = fopen("src.txt", "w");
    int srcpixel[256] = { 0 };
    int dirpixel[256] = { 0 };
    int p;//temp
    double srcprob[256];
    double dirprob[256] = {0};
    double zhong = src.rows*src.cols;
    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {

            p = src.at<uchar>(i, j);
            srcpixel[p]++;
        }
    }
    for (int i = 0; i < 255; i++)
    {
        srcprob[i] = srcpixel[i]/ zhong;
        fprintf(fp, "%lf  ", srcprob[i]);
        printf("srcpixel[%d]=%f\n", i, srcprob[i]);
    }
    double o=0;
    dirprob[0] = srcprob[0];
    for (int i = 1; i < 256; i++)
    {
        dirprob[i] = dirprob[i - 1] + srcprob[i];
    }
    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {
            p = src.at<uchar>(i, j);
            dir.at<uchar>(i, j) = 255 * dirprob[p];
        }
    }
    fclose(fp);
//  srcpixel[256] = { 0 };

    fp = fopen("dir.txt", "w");
    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {

            p = dir.at<uchar>(i, j);
            dirpixel[p]++;
        }
    }
    for (int i = 0; i < 255; i++)
    {
        srcprob[i] =dirpixel[i] / zhong;
        fprintf(fp, "%lf  ", srcprob[i]);
        printf("srcpixel[%d]=%f\n", i, srcprob[i]);
    }
    fclose(fp);



}
int main(int argc,char *argv[])
{

    Mat src= imread("3.jpg",0);
    Mat dir(src.rows,src.cols,CV_8UC1);
    imshow("src", src);
    //cvtColor(pic, pic, CV_BGR2GRAY);
    //imshow("12", pic);
    enhance(src, dir);
    imshow("drt", dir);
    imwrite("22.jpg", dir);
    waitKey();
}

這裡 src,dir表示原來影象和目標影象,先遍歷出各灰度值的畫素個數,計算出概率prob,通過公式轉化成目標影象的概率
fprintf將灰度值概率記下,方便用openGL或excel畫出直方圖進行比對

筆者能力有限,如有不足或錯誤歡迎指出