精华内容
下载资源
问答
  • 直方图绘制的时候用到了从父窗口获得成员数据或调用父窗口中的函数。这部分也是我参考网络上的程序写的,而建立非模态对话框也是。 获得父对话框窗口中的成员变量的值或调用父窗口中的函数的代码:CWnd* hParent=...
    我处理的是24位的真彩色图,所以会先将非灰度的24位图变换为灰度的24位图,然后进行。在直方图绘制的时候用到了从父窗口获得成员数据或调用父窗口中的函数。这部分也是我参考网络上的程序写的,而建立非模态对话框也是。
     
    获得父对话框窗口中的成员变量的值或调用父窗口中的函数的代码:
    CWnd* hParent=GetParent();
     CDIPDlg* dlg=(CDIPDlg*)hParent;
     char* m_dib=dlg->GetDibDataPoint();
     int m_nHeight=dlg->GetDibDataHeight();
     int m_nWidth=dlg->GetDibDataWidth();
     int m_nBitCount=dlg->GetDibDataBitCount();
    通过上面的dlg就可以引用到父对话框窗口中的成员变量或成员函数。
     
    建立非模态对话框的程序如下:
    CGrayHistPlotDlg* dlg=new CGrayHistPlotDlg();
     dlg->Create(IDD_DLG_GRAYHISTPLOT);
     dlg->ShowWindow(SW_SHOW);
    其中IDD_DLG_GRAYHISTPLOT是非模态对话框的资源表示,而在调用ShowWIndow的时候要用表示SW_SHOW。既然是非模态对话框,那么我的程序中的画直方图的代码都是在非模态对话框的OnPaint()函数中写的,全部程序如下:
    void CGrayHistPlotDlg::OnPaint()
    {
     CPaintDC dc(this); // device context for painting
     
     // TODO: Add your message handler code here
      
     //画坐标轴,横轴大小为270像素,纵轴大小为300像素
     //原点的坐标为(50,50+300),Y轴顶点坐标(50,50),X轴定点坐标(50+270,350)
     CPoint oPt;
     oPt.x=50;
     oPt.y=350;
     CPoint xPt;
     xPt.x=50+270;
     xPt.y=350;
     CPoint yPt;
     yPt.x=50;
     yPt.y=50;
     //画X轴和Y轴的直线
     dc.MoveTo(oPt);
     dc.LineTo(xPt);
     dc.MoveTo(oPt);
     dc.LineTo(yPt);
     //画X轴和Y轴的箭头
     //X轴的两个箭头坐标为x1(50+270-9,350+5),x2(50+270-9,350-5)
     //Y轴的两个箭头坐标为y1(50-5,50+9),y2(50+5,50+9)
     CPoint x1,x2;
     x1.x=50+270-9;
     x1.y=350+5;
     x2.x=50+270-9;
     x2.y=350-5;
     dc.MoveTo(xPt);
     dc.LineTo(x1);
     dc.MoveTo(xPt);
     dc.LineTo(x2);
     CPoint y1,y2;
     y1.x=50-5;
     y1.y=50+9;
     y2.x=50+5;
     y2.y=50+9;
     dc.MoveTo(yPt);
     dc.LineTo(y1);
     dc.MoveTo(yPt);
     dc.LineTo(y2);
     //标记原点,X轴和Y轴
     CRect oRect;
     oRect.top=oPt.y+2;
     oRect.left=oPt.x;
     oRect.right=oRect.left+10;
     oRect.bottom=oRect.top+15;
     dc.DrawText("O",oRect,DT_WORDBREAK|DT_CENTER);
     CRect xRect;
     xRect.left=x1.x;
     xRect.top=x1.y+2;
     xRect.right=xRect.left+10;
     xRect.bottom=xRect.top+15;
     dc.DrawText("X",xRect,DT_CENTER);
     CRect yRect;
     yRect.top=y1.y;
     yRect.left=y1.x-10;
     yRect.right=yRect.left+10;
     yRect.bottom=yRect.top+15;
     dc.DrawText("Y",yRect,DT_CENTER);
     //获得绘制直方图所需要的数据
     CWnd* hParent=GetParent();
     CDIPDlg* dlg=(CDIPDlg*)hParent;
     char* m_dib=dlg->GetDibDataPoint();
     int m_nHeight=dlg->GetDibDataHeight();
     int m_nWidth=dlg->GetDibDataWidth();
     int m_nBitCount=dlg->GetDibDataBitCount();
     int nCount[256];
     for(int i=0;i<256;i++) nCount[i]=0;
     long LineBytes=((m_nWidth*m_nBitCount)+31)/32*4;
     for(i=0;i<m_nHeight;i++)
     {
      for(int j=0;j<LineBytes;j++)
      {
       BYTE B=*(m_dib+LineBytes*i+j);
       j++;
       j++;
       nCount[B]++;
      }
     }
     //处理直方图的数据,使其在一定的范围内
     int max=0;
     for(i=0;i<256;i++)
     {
      if(nCount[i]>max) max=nCount[i];
     }
     for(i=0;i<256;i++)
     {
      if(max==0)
      {
       AfxMessageBox("error");
       return;
      }
      nCount[i]=static_cast<int>((nCount[i]*300)/max);
     }
     //绘制直方图
     BYTE w=2;
     for(i=0;i<256;i++)
     {
      //每条直线用两个像素的宽度来画,即为一个宽为2的矩形条
      for(int j=0;j<w;j++)
      {
       dc.MoveTo(CPoint(50+i+j,350));
       dc.LineTo(CPoint(50+i+j,350-nCount[i]));
      }
     }
     //X轴的一些刻度
     //刻度“50”
     CRect r50;
     r50.left=oPt.x+50;
     r50.top=oPt.y+20;
     r50.right=r50.left+20;
     r50.bottom=r50.top+15;
     dc.DrawText("50",r50,DT_CENTER);
     //画刻度50处的向上箭头
     //pt501为箭头的下面的点,pt502为箭头的上面的点
     //pt503为箭头的左边的点,pt504为箭头的右边的点
     CPoint pt501,pt502,pt503,pt504;
     pt501.x=r50.left;
     pt501.y=r50.top-2;
     pt502.x=pt501.x;
     pt502.y=pt501.y-15;
     pt503.x=pt502.x-3;
     pt503.y=pt502.y+3;
     pt504.y=pt503.y;
     pt504.x=pt502.x+3;
     dc.MoveTo(pt501);
     dc.LineTo(pt502);
     dc.MoveTo(pt502);
     dc.LineTo(pt503);
     dc.MoveTo(pt502);
     dc.LineTo(pt504);
     //刻度“100”
     CRect r100;
     r100.left=oPt.x+100;
     r100.top=oPt.y+20;
     r100.right=r100.left+30;
     r100.bottom=r100.top+15;
     dc.DrawText("100",r100,DT_CENTER);
     //画刻度100处向上箭头
     //pt1001为箭头的下面的点,pt1002为箭头的上面的点
     //pt1003为箭头的左边的点,pt1004为箭头的右边的点
     CPoint pt1001,pt1002,pt1003,pt1004;
     pt1001.x=r100.left;
     pt1001.y=r100.top-2;
     pt1002.x=pt1001.x;
     pt1002.y=pt1001.y-15;
     pt1003.x=pt1002.x-3;
     pt1003.y=pt1002.y+3;
     pt1004.y=pt1003.y;
     pt1004.x=pt1002.x+3;
     dc.MoveTo(pt1001);
     dc.LineTo(pt1002);
     dc.MoveTo(pt1002);
     dc.LineTo(pt1003);
     dc.MoveTo(pt1002);
     dc.LineTo(pt1004);
     //刻度“150”
     CRect r150;
     r150.left=oPt.x+150;
     r150.top=oPt.y+20;
     r150.right=r150.left+30;
     r150.bottom=r150.top+15;
     dc.DrawText("150",r150,DT_CENTER);
     //画刻度150处向上箭头
     //pt1501为箭头的下面的点,pt1502为箭头的上面的点
     //pt1503为箭头的左边的点,pt1504为箭头的右边的点
     CPoint pt1501,pt1502,pt1503,pt1504;
     pt1501.x=r150.left;
     pt1501.y=r150.top-2;
     pt1502.x=pt1501.x;
     pt1502.y=pt1501.y-15;
     pt1503.x=pt1502.x-3;
     pt1503.y=pt1502.y+3;
     pt1504.y=pt1503.y;
     pt1504.x=pt1502.x+3;
     dc.MoveTo(pt1501);
     dc.LineTo(pt1502);
     dc.MoveTo(pt1502);
     dc.LineTo(pt1503);
     dc.MoveTo(pt1502);
     dc.LineTo(pt1504);
     //刻度“200”
     CRect r200;
     r200.left=oPt.x+200;
     r200.top=oPt.y+20;
     r200.right=r200.left+30;
     r200.bottom=r200.top+15;
     dc.DrawText("200",r200,DT_CENTER);
     //画刻度200处向上箭头
     //pt2001为箭头的下面的点,pt2002为箭头的上面的点
     //pt2003为箭头的左边的点,pt2004为箭头的右边的点
     CPoint pt2001,pt2002,pt2003,pt2004;
     pt2001.x=r200.left;
     pt2001.y=r200.top-2;
     pt2002.x=pt2001.x;
     pt2002.y=pt2001.y-15;
     pt2003.x=pt2002.x-3;
     pt2003.y=pt2002.y+3;
     pt2004.y=pt2003.y;
     pt2004.x=pt2002.x+3;
     dc.MoveTo(pt2001);
     dc.LineTo(pt2002);
     dc.MoveTo(pt2002);
     dc.LineTo(pt2003);
     dc.MoveTo(pt2002);
     dc.LineTo(pt2004);
     //刻度“255”
     CRect r255;
     r255.left=oPt.x+255;
     r255.top=oPt.y+20;
     r255.right=r255.left+30;
     r255.bottom=r255.top+15;
     dc.DrawText("255",r255,DT_CENTER);
     //画刻度255处向上箭头
     //pt2551为箭头的下面的点,pt2552为箭头的上面的点
     //pt2553为箭头的左边的点,pt2554为箭头的右边的点
     CPoint pt2551,pt2552,pt2553,pt2554;
     pt2551.x=r255.left;
     pt2551.y=r255.top-2;
     pt2552.x=pt2551.x;
     pt2552.y=pt2551.y-15;
     pt2553.x=pt2552.x-3;
     pt2553.y=pt2552.y+3;
     pt2554.y=pt2553.y;
     pt2554.x=pt2552.x+3;
     dc.MoveTo(pt2551);
     dc.LineTo(pt2552);
     dc.MoveTo(pt2552);
     dc.LineTo(pt2553);
     dc.MoveTo(pt2552);
     dc.LineTo(pt2554);
     // Do not call CDialog::OnPaint() for painting messages
    }
    运行时的效果图片如下:
    界面如下:
    10.jpg
     
    点击“直方图曲线”后的绘制的直方图如下:
    11.jpg
     
    点“直方图均衡”之后,得到直方图如下:
    12.jpg
     
    另外,如果你的绘图程序在最小化之后不能显示了,或者是被别的窗口挡住之后,图片都显示的不完整了,那么你可以在对话框的onPaint()函数总写上重画图形的代码,这样就不会再窗口最小化之后就没有图片了。像我的主程序中的OnPaint()函数中就有重画的代码:
    void CDIPDlg::OnPaint()
    {
     if (IsIconic())
     {
      CPaintDC dc(this); // device context for painting
      SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
      // Center icon in client rectangle
      int cxIcon = GetSystemMetrics(SM_CXICON);
      int cyIcon = GetSystemMetrics(SM_CYICON);
      CRect rect;
      GetClientRect(&rect);
      int x = (rect.Width() - cxIcon + 1) / 2;
      int y = (rect.Height() - cyIcon + 1) / 2;
      // Draw the icon
      dc.DrawIcon(x, y, m_hIcon);
     }
     else
     {
      CDialog::OnPaint();
      CDC* pDC=GetDC();
      BYTE* lpdib=(BYTE*)::GlobalLock((HGLOBAL)m_hDIB);
      BITMAPINFO* m_pBitmapInfo=(BITMAPINFO*)lpdib;
      ::StretchDIBits(pDC->m_hDC,10,10,m_nWidth,m_nHeight,0,0,m_nWidth,m_nHeight,m_pDibData,m_pBitmapInfo,DIB_RGB_COLORS,SRCCOPY);
      ::GlobalUnlock((HGLOBAL)m_hDIB);
     }
    }
    展开全文
  • 直方图均衡VC6编写

    2009-12-26 22:11:45
    实现位图直方图均衡处理,有详细的处理过程!
  • 如果,如果你要做的是8位图直方图均衡化,别看了。前方左转查查histeq怎么用,挺简单的,另我是个新手,不会用matlab,所以在这里记录下histeq怎么用,不看往下翻。 8位图 histeq函数 16位图 代码 function [img2] =...

    前言

    如果,如果你要做的是8位图直方图均衡化,别看了。前方左转查查histeq怎么用,挺简单的,另我个新手上路,不会用matlab,所以在这里记录下histeq怎么用,不看往下翻。

    8位图 histeq函数

    8位tif灰度图像图像

    灰度图就很方便了,I是读取到的数组,用histeq将I做均衡化,用I1存储生成的数组,用figure显示出来

    I = imread(‘xxx.tif’);
    I1 = histeq(I);
    figure,imshow(I1,[])
    

    好的这里如果要存储的话,反正是8位的图像嘛,这里就直接用

    imwrite(I1,'m.jpeg')
    

    就可以了

    8位bmp rgb图像

    好的如果是8位的或者不知道多少位的bmp rgb图像的话,如果只是追求这个函数可以使用,那么,可以试试我这个方案

     F=imread('D:\Project\直方图均衡\Pic\1.bmp');
     F1=rgb2gray(F);
     F2 = histeq(F1);
     figure,imshow(F2,[])
    

    其他操作同上

    16位 raw文件读取

    怎么读取找了半天,不重开一个文章了都记录在这吧
    下面两行代码,把从fid读取到的数据存放到b这个数组里,[300,200]是文件大小,注,第一个参数一定要对,第二个无所谓。‘int16’是数据格式,8位的话就int8

    fid=fopen('D:\Project\直方图均衡\Pic\0.Raw', 'r');
    [b,count]=fread(fid,[300,200],'int16');
    

    好的,另外你应该知道那个‘’单引号内部的是图像路径吧? 还有就是matlab左边的那个路径在的地方,被matlab视为根位置,对放在这个地方的文件不用前面的那一堆,可以直接写文件名,懂吧?

    16位图 代码

    不知道matlab代码怎么插入,用的lua脚本的格式凑合着看吧

    function [img2] = a(img)
        img1 = double(img);
        [r,c] = size(img1);%获取图像的高r和宽c
        %统计图像中每个灰度级i出现的次数存到count(1,i)里
        count = zeros(1,65536);
        for i=1:r
            for j=1:c
                count(1,img(i,j)+1) = count(1,img(i,j)+1)+1;
            end
        end
        %统计图像中每个灰度级i出现的概率,存储到p(1,i)里
        p = zeros(1,65536);
        for i=1:65536
            p(1,i) = count(1,i)/(r*c);
        end
        img2 = im2uint8(ones(r,c));%创建一个r * c大小的1矩阵
        
        func_T = zeros(1,65536);%变换映射存储
        p_sum = 0;
        %求直方图均衡化的变换函数
        for k = 1:65536
            p_sum = p_sum + p(k);%求每个灰度级的概率之和
            func_T(k) = 255*p_sum;%根据变换函数的公式求每一点k对应的映射值
        end
        
        func_T_z =  round(func_T);%对变换函数进行取整,round 为四舍五入取整
        %完成每个像素点的映射
        for i = 0:255
            findi = find(func_T_z==i);%找到灰度级为i的概率和
            len = length(findi);
            for j=1:len
                findj = find(img==(findi(j)-1));%进行对应每个像素点的映射
                img2(findj) = i;
            end
        end
    end
    

    不确定有没有bug,觉得有问题的千万指出…把这个保存成a.mat文件放在matlab目录里,就可以直接调用啦,传入数组是刚从raw里读出来的b。

    参考:

    matlab实现 图像的直方图均衡化处理 直方图均衡化 代码

    展开全文
  • C++ 位图的读写、几何变换、傅里叶变换与直方图均衡
  • 使用 c 编译器或涡轮 c
  • 直方图均衡

    2009-01-04 10:10:00
    可以对8位或24位位图进行直方图均衡 均衡前的图片和直方图: 直方图均衡后的图片和直方图: void CICETIMDlg::OnBtnGrayhistenhance() { // TODO: Add your control notification handler code here int ...
    可以对8位或24位位图进行直方图均衡
     
    均衡前的图片和直方图:
    1.bmp
    4.bmp
     
    直方图均衡后的图片和直方图:
    2.bmp
    3.bmp
     
    void CICETIMDlg::OnBtnGrayhistenhance()
    {
     // TODO: Add your control notification handler code here
     int nHeight=m_dib.GetHeight();
     if(nHeight==0)
     {
      AfxMessageBox("请先打开位图");
      return;
     }
     int nBitCount=m_dib.GetBitCount();
     int lLineBytes=m_dib.GetLineBytes();
     int nWidth=m_dib.GetWidth();
     BYTE* m_image=m_dib.GetDibData();
     BYTE* newImage=new BYTE[nHeight*lLineBytes];
     memset(newImage,0,nHeight*lLineBytes);
     int nCount[256];
     for(int i=0;i<256;i++)
     {
      nCount[i]=0;
     }
     for(i=0;i<nHeight;i++)
     {
      for(int j=0;j<lLineBytes;j++)
      {
       if(nBitCount==8)
       {
        BYTE B=*(m_image+lLineBytes*i+j);
        nCount[B]++;
       }
       else if(nBitCount==24)
       {
        BYTE B=*(m_image+lLineBytes*i+j);
        nCount[B]++;
        j++;
        j++;
       }
       else
       {
        AfxMessageBox("暂时只能处理8或24位位图");
        return;
       }
      }
     }
     long lTemp=0;
     for(i=0;i<256;i++)
     {
      lTemp+=nCount[i];
      nCount[i]=(lTemp*255/nHeight/nWidth);
      if(nCount[i]<0) nCount[i]=0;
      if(nCount[i]>255) nCount[i]=255;
      for(int m=0;m<nHeight;m++)
      {
       for(int n=0;n<lLineBytes;n++)
       {
        if(nBitCount==8)
        {
         if(*(m_image+lLineBytes*m+n)==i)
         {
          *(newImage+lLineBytes*m+n)=nCount[i];
         }
        }
        else if(nBitCount==24)
        {
         if(*(m_image+lLineBytes*m+n)==i)
         {
          *(newImage+lLineBytes*m+n)=nCount[i];
          n++;
          *(newImage+lLineBytes*m+n)=nCount[i];
          n++;
          *(newImage+lLineBytes*m+n)=nCount[i];
          n--;
          n--;
         }
        }
        else
        {
         AfxMessageBox("暂时只能处理8或24位位图");
         return;
        }
       }
      }
     }
     m_dib.SetDibData(newImage);
     ShowImage(m_dib,"直方图均衡");
    }
    展开全文
  • 灰度变换 灰度 灰度可以认为是亮度,灰色图片中黑白的深浅程度,范围一般为0~255。图像数字化为二维矩阵后,每个点的值都代表一个像素点的灰度值。 灰度级 ...灰度值的表示范围,灰度级时,称图片为...空间域处理...

    灰度变换 

    灰度

    灰度可以认为是亮度,灰色图片中黑白的深浅程度,范围一般为0~255。图像数字化为二维矩阵后,每个点的值都代表一个像素点的灰度值。

    灰度级

    L=2^{k}

    灰度值的表示范围,2^{k}灰度级时,称图片为k比特图片。当然灰度级越高,图片的细节则越清晰,因为有更多的灰度值来描述图片。但是灰度级越大,图片所需要的存储空间也会越大,因此一般会采用256灰度级。

    灰度变换  空间滤波

    g(x,y)=T\left [ f(x,y) \right ]

    空间域处理图像(直接对f(x,y)进行操作)T[  ]就像是一个操作的函数,将图像f (x,y)输入后会进行不同的操作,操作结果为g (x,y)。

    S=T(r)

    一般用上述形式表示变换的过程,r和S分别表示变换前后的像素值(灰度),T表示某种变换函数

    目前学到的有灰度变换和空间滤波,灰度变换包括图像反转,对数变换,幂次变换,直方图均衡、匹配,空间滤波包括平滑滤波和锐化滤波

    图像反转

    这里主要是线性变换,将某一范围的灰度值映射到另一个线性范围

    S=L-1-r (r\subset [0,L-1])

    我们对某位患者的胸片进行处理,原图中有白色絮状物体,但是图片整体偏暗,不便于观察,于是我们进行线性的反转,将较亮部位与较暗部位进行互换,如下图所示,肉眼可见观察的更加清晰了。

    胸片 线性变换

    图像反转代码

    imadjust(f,[low_in, high_in ],[low_out, high_out])将图片的[low_in, high_in]范围映射到[low_out, high_out],我们需要进行反转,就将low_out > low_in 

    f=imread('C:\Matlab Project\image\Fig0303(a)(breast).tif');
    g=imadjust(f,[0 0.8],[1 0]);
    figure(1)
    title('图像反转');
    subplot(1,2,1);imshow(f)
    subplot(1,2,2);imshow(g)
    

    对数变换

    S=c*log(1+r)

    对数变换

    根据对数函数的特征,会将输入图像的灰度值中较暗部分 r < L/4 部分映射到 [0  3L/4]这个较大的范围,而较亮部分则会映射到较小的区域。这个函数会将图像暗处的细节放大,压缩亮处的细节。最具代表的就是对傅里叶频谱的对数运算,从对比图中可以看到暗处的细节被放大输出

    对数变换

    代码

    f=imread('C:\Matlab Project\image\Fig0305(a)(spectrum).tif');
    g=0.8*log(1+double(f));
    figure()
    subplot(1,2,1);imshow(f)
    subplot(1,2,2);imshow(g)

    幂次变换

    S=C*r^{\gamma }

    \gamma<1时,效果和对数函数相似,放大暗处细节,压缩亮处细节,随着数值减少,效果越强

    \gamma>1时,放大亮处细节,压缩暗处细节,随着数值增大,效果越强

    代码

    测试为\gamma>1的情况,图片效果和对数变换差别不大

    测试\gamma=0.1的情况,将暗处细节放大,亮处细节压缩

    f=imread('C:\Matlab Project\image\Fig0305(a)(spectrum).tif');
    g=double(f).^0.1;
    figure()
    subplot(1,2,1);imshow(f,[])
    subplot(1,2,2);imshow(g,[])

    测试\gamma=10的情况,将暗处细节放大,压缩亮出细节,图片变得更暗了

    f=imread('C:\Matlab Project\image\Fig0305(a)(spectrum).tif');
    g=double(f).^10;
    figure()
    subplot(1,2,1);imshow(f,[])
    subplot(1,2,2);imshow(g,[])

    位图切割

    由于灰度级L=2^{k},是有2的次方构成,每个像素值看作是由K个二进制数组成的

    r=a1*2^{k-1}+a2*2^{k-2}....+a7*2^1+a8*2^0

    于是每个平面k-1,k-2,....,1,0 中的每一个像素值都等于该像素在该平面的项数值

    代码

    感觉有些冗余,但是目前还不知道怎么修改,以后再改

    f=imread('C:\Matlab Project\image\original_test_pattern.tif');
    g=double(f);
    L1=mod(g,2);
    L2=mat2gray(mod(g./2,2));
    L3=mat2gray(mod(g./(2.^2),2)); 
    L4=mat2gray(mod(g./(2.^3),2)); 
    L5=mat2gray(mod(g./(2.^4),2)); 
    L6=mat2gray(mod(g./(2.^5),2)); 
    L7=mat2gray(mod(g./(2.^6),2)); 
    L8=mat2gray(mod(g./(2.^7),2)); 
    figure()
    subplot(3,3,1);imshow(L1),title('第一层');
    subplot(3,3,2);imshow(L2),title('第二层');
    subplot(3,3,3);imshow(L3),title('第三层');
    subplot(3,3,4);imshow(L4),title('第四层');
    subplot(3,3,5);imshow(L5),title('第五层');
    subplot(3,3,6);imshow(L6),title('第六层');
    subplot(3,3,7);imshow(L7),title('第七层');
    subplot(3,3,8);imshow(L8),title('第八层');
    subplot(3,3,9);imshow(f),title('原图');

    直方图 均衡 匹配

    直方图:

     h(r_{k})=n_{k}   表示像素值r_{k}在图像中出现的次数n_{k},下图显示的是图片对应的直方图

    代码

    f=imread('C:\Matlab Project\image\Fig0308(a)(pollen).tif');
    h1=imhist(f,256); %函数imhist 得到一维数组频数 不直接输出
    h2=h1(1:10:256); %转化为条形图
    horz=1:10:256;
    figure()
    subplot(1,2,1);imshow(f);
    subplot(1,2,2); h2=bar(horz,h2,0.6);
    axis([0 255 0 15000]) %直方图输出范围(横0-256 纵 0-15000 )
    set(gca,'xtick',0:50:255)
    set(gca,'ytick',0:2000:12000)

    直方图均衡

    归一化直方图:P(r_{k})=n_{k}/n  表示像素值r_{k}在图像中出现的概率

    S=T(r)=\sum_{j=0}^{k}P_{r}(r_{j})=\sum_{j=0}^{k}n_{j}/n

    可以将函数变换到直方图较均衡分布的状态

    直方图变换的S=T(r)函数,通过归一化直方图相加获得

    代码

    matlab 中使用histeq(f,256)直接获得均衡后的图像

    f=imread('C:\Matlab Project\image\Fig0308(a)(pollen).tif');
    h1=imhist(f,256);
    h2=histeq(f,256);  %histeq均衡后得到为图像
    figure(1)
    subplot(2,2,1);imshow(f);
    subplot(2,2,2);plot(h1);
    subplot(2,2,3);imshow(h2);
    subplot(2,2,4);imhist(h2); 
    
    hnorm=imhist(f)./numel(f);  %注意为原图像的概率,不是均衡后的
    cdf=cumsum(hnorm);  % 变换函数S=T(r)
    x=linspace(0,1,256);
    figure(2)
    plot(x,cdf);
    axis([0 1 0 1])
    set(gca,'xtick',0:0.2:1)
    set(gca,'ytick',0:0.2:1)

    直方图匹配

    直方图匹配是在均衡的基础上进行,希望最后处理后的图像符合某种特定的直方图分布。为什么要这样呢,主要是因为均衡是将整个图像整体的均衡,可能将整体的图片变化的太暗或是太亮,如图,左边为原图,中间为直方图均衡,右边为直方图匹配。

    通过下图直方图均衡的变化函数S=T(r),也能看出,均衡将函数值变得偏大,图像便整体偏大

    再分析图像变化前后的直方图分布,我们可以发现,原图的像素值主要分布在较暗和较亮两个极端位置,但是直方图均衡就粗暴的将大家都平均了。

    假设我们希望最后图像归一化直方图为P_{z}(z)

    求相应的变换函数

    G(z)=\sum_{i=0}^{q}P_{z}(Z_{i})

    而输入图像的变换函数为S=T(r)

    我们希望他们相等

    G(z)=T(r)

    便可求出S到Z的映射

    代码

    matlab 通过  histeq(f,hspec) 函数来实现,hspec为最后希望的直方图

    由于输入图像的直方图类似双峰高斯函数,所以我们将hspec设置为双峰高斯函数由函数twomodegauss获得

    twomodegauss

    function p = twomodegauss(m1,sig1,m2,sig2,A1,A2,k)
    %TWOMODEGAUSS 返回双峰高斯函数
    %   p = twomodegauss(m1,sig1,m2,sig2,A1,A2,k)
    %   p为标准化256个元素,sum(p)=1,
    %  (m1,sig1),(m2,sig2)分别为双峰的均值和标准差,
    %  A1,A2分别为峰值,k为基数
    
    c1 = A1 * (1 / ((2 * pi) ^ 0.5) * sig1);
    k1 = 2 * (sig1 ^ 2);
    c2 = A2 * (1 / ((2 * pi) ^ 0.5) * sig2);
    k2 = 2 * (sig2 ^ 2);
    z = linspace(0, 1, 256);
    
    p = k+c1*exp(-((z-m1).^2)./k1)+c2*exp(-((z-m2).^2)./k2);
    p = p./sum(p(:));
    

    实现代码

    f=imread('C:\Matlab Project\image\Fig0310(a)(Moon Phobos).tif');
    p = twomodegauss(0.15,0.05, 0.75, 0.05,1, 0.07, 0.002);
    g=histeq(f,p);
    figure(1)
    subplot(1,3,1);imshow(f);
    subplot(1,3,2);imshow(histeq(f,256));
    subplot(1,3,3);imshow(g);
    

     

     

     

    展开全文
  • 虽然窗口显示了位图,为什么显示的直方图空白?怎样才能调用窗口里的位图信息?
  • 图像的直方图均衡 #include"bmp.h" #include #include #include #include int* m_histArray; void Bitmap::releasedHist() { if (m_histArray != NULL) delete[] m_histArray; } //说明:灰度图像统计直方图,...
  • //直方图均衡化 void CalculateCDF(double *p);//计算累计分布函数 }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif ...
  • 万丈高楼平地起 C语言大作业 一、学习笔记篇 1.学习MarkDown MarkDown注重写作本身,而非花俏的界面 ...可以分成两类:设备有向量相关位图(DDB)和设备无向量相关位图(DIB)。 1.进制表示 H 表示该...
  • 图像的直方图均衡 #include"bmp.h" #include<cmath> #include<cstring> #include<cstdio> #include<iostream> int* m_histArray; void Bitmap::releasedHist() { if (m_histArray != ...
  • 图像的几何变换(针对位图) /** 作者:Corfox Liu 时间:2014.12.24 参考书籍:Visual C++数字图像处理(谢凤英) */ #include"bmp.h" #include #include #include #include using namespace std; void Bitmap::...
  • 位图的读写 #include"bmp.h" #include #include #include using namespace std; Bitmap::Bitmap() { } Bitmap::~Bitmap() { if (dataBuf!=NULL) delete[] dataBuf; dataBuf = NULL; if (colorTable != ...
  • //将频谱以图像形式存入imgBufOut float t; int i0, j0; for (i = 0; i; i++){ //i0 = i; //j0 = j; for (j = 0; j; j++){ if (i) i0 = i + height_p / 2; else i0 = i - height_p / 2; ...
  • 定义一个Bitmap类,具有位图读写、几何变换、傅里叶变换、直方图均衡操作。文件名bmp.h #include //复数类 class ComplexNumber { public: float imag;//虚部 float real;//实部 }; class Bitmap { private...
  • 位图的读写 #include"bmp.h" #include<iostream> #include<cstring> #include<cstdio> using namespace std; Bitmap::Bitmap() { } Bitmap::~Bitmap() { if (dataBuf!=NULL) ...
  • //将频谱以图像形式存入imgBufOut float t; int i0, j0; for (i = 0; i; i++){ //i0 = i; //j0 = j; for (j = 0; j; j++){ if (i) i0 = i + height_p / 2; else i0 = i - height_p / 2; ...
  • 定义一个Bitmap类,具有位图读写、几何变换、傅里叶变换、直方图均衡操作。文件名bmp.h #include //复数类 class ComplexNumber { public: float imag;//虚部 float real;//实部 }; class Bitmap { private: ...
  • //输出图像坐标为(j,i)的像素映射到原中的坐标值,即插值位置 coordinateX = w / ratioX; coordinateY = h / ratioY; //对插值位置坐标取整 Iu = (int)coordinateX; Iv = (int)coordinateY; //若插值位置在...
  • 位图处理,灰度直方图统计及均衡化,几何变化,噪声处理,文档图像的生成。高斯滤波,均值滤波等以及齐全的软件工程文档。
  • 图像直方图统计及其C语言实现(附源码)

    千次阅读 多人点赞 2019-10-23 13:27:49
    本文内容主要给大家介绍数字图像处理领域中直方图的相关内容以及在C语言下的实现,重点介绍了BMP图像文件格式,对于进一步的直方图均衡、直方图匹配、局部直方图处理等内容之后会陆续推出。 目录 1.直方图 2....
  • 代码实现了打开一个bmp位图文件,然后进行均衡化处理。
  • 直方图处理4.1 生成并绘制图像直方图4.2 直方图均衡化 空间域图像增强 图像增强是图像处理中最具吸引力的领域之一,增强处理的首要目标是处理图像,对图像进行加工,使其比原始图像更适合特定的应用。空间域是指...
  • 这次我主要在BMP位图照片的读取和显示的基础上,加上了对BMP位图照片的灰度变换。都是一层层上来的,这次不打算...直方图均衡 反转 阀值变换 分段线性拉伸step1. 绘制菜单栏 step2. 接下来,我们对”灰度变换“下的
  • matlab开发-Cprogram

    2019-08-24 13:38:45
    matlab开发-Cprogram。用于直方图、直方图均衡、TIFF和位图的C程序
  • 这是一个用VC++实现的图像处理和图像分割系统,它能够对图像进行直方化,均衡化,均值滤波,灰度化,并且还能实现对图像进行边缘检测,区域生长,迭代阈值和直方图分割。能够对8位,16位和32位的.bmp位图进行处理
  • 一个完整的VC++基本图像处理工程,为本人课程设计,具备基本图像增强算法的实现。 包含: 打开位图图片 均值滤波 中值滤波 直方图均衡化 保存位图文件 全部代码有注释。
  • 数字图像处理源代码

    2012-11-23 21:10:44
    根据图像的直方图,进行直方图均衡化,实现图像增强 3.可在直方图上拖动鼠标,进行阈值的选取,实现二值化 4.能够保存得到的二值化位图 三、位图的几何变换 1、平移变换 2、旋转变换 3、缩放变换 4、双线性...

空空如也

空空如也

1 2 3
收藏数 48
精华内容 19
关键字:

位图直方图均衡