如果您想了解bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟和bmp位图的知识,那么本篇文章将是您的不二之选。我们将深入剖析bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟的各个方面,并为
如果您想了解bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟和bmp 位图的知识,那么本篇文章将是您的不二之选。我们将深入剖析bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟的各个方面,并为您解答bmp 位图的疑在这篇文章中,我们将为您介绍bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟的相关知识,同时也会详细的解释bmp 位图的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟(bmp 位图)
- 5-3 直方图均衡化
- c#数字图像处理(五)全等级直方图灰度拉伸
- c#数字图像处理(六)直方图均衡化
- C语言实现BMP图像处理(直方图均衡化)
bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟(bmp 位图)
#if !defined(AFX_WAVEDLG_H__3AD6300B_435E_4773_8C88_DDE56BEE2A52__INCLUDED_)
#define AFX_WAVEDLG_H__3AD6300B_435E_4773_8C88_DDE56BEE2A52__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
/////////////////////////////////////////////////////////////////////////////
// CWaveDlg dialog
class CWaveDlg : public CDialog
{
// Construction
public:
CWaveDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
//{{AFX_DATA(CWaveDlg)
enum { IDD = IDD_WAVE_DIALOG };
CSliderCtrl m_slider2;
CSliderCtrl m_sliderCtr;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWaveDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
//{{AFX_MSG(CWaveDlg)
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnStaticWave();
afx_msg void OnButtonTest();
afx_msg void OnDestroy();
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
afx_msg void OnCancelMode();
afx_msg void OnTimer(UINT nIDEvent);
virtual void OnOK();
afx_msg void OnButton2();
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnMenuitemRgbToGray();
afx_msg void OnMenuitemOrgImag();
afx_msg void OnMenuitemBinary();
afx_msg void OnButtonScrollWnd();
afx_msg void OnMenuitemInvertY();
afx_msg void OnMenuitemInvertX();
afx_msg void OnMenuitemHisto();
afx_msg void OnMenuitemSaveGray8bit();
afx_msg void OnMenuitemSaveBinaryBmp1bit();
afx_msg void OnMenuitemGlobGrayStretch();
afx_msg void OnMenuitemHistoEqualization();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
double m_dbPercent;
byte m_bBrightness;
int m_nPoolWid;
int m_nPoolHei;
CBitmap m_bmp,m_newBmp;
int * m_pPoolBuff,*m_pPoolBuff1;
byte *m_pImageDateBuff,*m_pImageDateBuff1;
CDC* m_pDC;
double GetDistance(const CPoint & p1,const CPoint &p2);
int GetAmplitude(int a0,int a1,int a2,int a3,int a4);
int GetEnergyFromWaterSourece(const CPoint &ptCenter,const CPoint &pt,double radius,int energy=50);
CBrush m_brush;
void Shocking();
void RefreshImag(void);
void AdjustContrastAndBrightness(void);//调节对比度亮度
INT m_nCount;
void LimitMaxMin(byte& val)
{
if (val>255)
{
val =255;
}
if (val<0)
{
val= 0;
}
}
void AvgChannels(int & r,int &g,int &b);
void AdjustSimpleContrastAndBrightness(void);//调节对比度亮度
void Rgb2Gray24(int typeFlag);
void Gray2Binary(byte* imageBuffer,byte threshold);
void SaveBmp(void);
void SaveBmpSingle(void);//8bit单色位图
void SaveBmpBinary(void);//1bit单色位图
void InvertBuffer(INT direction);
void RoateImag(CPoint & roatePos,double roateAngle);
void GetHistogram(int *Histo);
void DrawHistoGram(int *Histo);
void Rgb2Gray8(void);
void Rgb2Gray16(void);
void Rgb2Rgb8(void);
void Rgb2Rgb16(void);
void GlobGrayStrench();//全局灰度直方图拉伸
void HistogramEqualization(void);//直方图均衡化
void CalculateCDF(double *p);//计算累计分布函数
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WAVEDLG_H__3AD6300B_435E_4773_8C88_DDE56BEE2A52__INCLUDED_)
////////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Wave.h"
#include "WaveDlg.h"
#include<MATH.H>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CWaveDlg::CWaveDlg(CWnd* pParent /*=NULL*/)
: CDialog(CWaveDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CWaveDlg)
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_dbPercent=0.0;
m_nCount=1;
int len=6;
while (len--)
{
int a=len;
}
}
void CWaveDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CWaveDlg)
DDX_Control(pDX, IDC_SLIDER2, m_slider2);
DDX_Control(pDX, IDC_SLIDER, m_sliderCtr);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CWaveDlg, CDialog)
//{{AFX_MSG_MAP(CWaveDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_STATIC_WAVE, OnStaticWave)
ON_BN_CLICKED(IDC_BUTTON_TEST, OnButtonTest)
ON_WM_DESTROY()
ON_WM_CTLCOLOR()
ON_WM_CANCELMODE()
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
ON_WM_HSCROLL()
ON_COMMAND(ID_MENUITEM_RGB_TO_GRAY, OnMenuitemRgbToGray)
ON_COMMAND(ID_MENUITEM_ORG_IMAG, OnMenuitemOrgImag)
ON_COMMAND(ID_MENUITEM_BINARY, OnMenuitemBinary)
ON_BN_CLICKED(IDC_BUTTON_SCROLL_WND, OnButtonScrollWnd)
ON_COMMAND(ID_MENUITEM_INVERT_Y, OnMenuitemInvertY)
ON_COMMAND(ID_MENUITEM_INVERT_X, OnMenuitemInvertX)
ON_COMMAND(ID_MENUITEM_HISTO, OnMenuitemHisto)
ON_COMMAND(ID_MENUITEM_SAVE_GRAY_8BIT, OnMenuitemSaveGray8bit)
ON_COMMAND(ID_MENUITEM_SAVE_BINARY_BMP_1BIT, OnMenuitemSaveBinaryBmp1bit)
ON_COMMAND(ID_MENUITEM_GLOB_GRAY_STRETCH, OnMenuitemGlobGrayStretch)
ON_COMMAND(ID_MENUITEM_HISTO_EQUALIZATION, OnMenuitemHistoEqualization)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CWaveDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application''s main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_bmp.LoadBitmap(IDB_BITMAP);
BITMAP bitMap;
m_bmp.GetBitmap(&bitMap);
m_nPoolWid=bitMap.bmWidth;
m_nPoolHei=bitMap.bmHeight;
GetDlgItem(IDC_STATIC_WAVE)->SetWindowPos(NULL,0,0,m_nPoolWid,m_nPoolHei,SWP_NOMOVE);
m_pDC=GetDlgItem(IDC_STATIC_WAVE)->GetDC();
int size=m_nPoolHei*m_nPoolWid;
m_pPoolBuff=new int[size];
m_pPoolBuff1=new int[size];
memset(m_pPoolBuff,0,size*sizeof(int));
memset(m_pPoolBuff1,0,size*sizeof(int));
int ImageDateSize=size*bitMap.bmBitsPixel/8;
m_pImageDateBuff=new byte[ImageDateSize];
m_pImageDateBuff1=new byte[ImageDateSize];
m_bmp.GetBitmapBits(ImageDateSize,m_pImageDateBuff);
//m_newBmp.CreateCompatibleBitmap(m_pDC,m_nPoolWid,m_nPoolHei);
m_newBmp.CreateBitmap(m_nPoolWid,m_nPoolHei,1,32,m_pImageDateBuff);
//m_newBmp.CreateBitmapIndirect(&bitMap);
//m_newBmp.CreateDiscardableBitmap(m_pDC,m_nPoolWid,m_nPoolHei);
// //m_newBmp.SetBitmapBits(ImageDateSize,m_pImageDateBuff);
m_brush.CreateSolidBrush(RGB(255,0,0));
m_sliderCtr.SetRangeMax(100,TRUE);
m_sliderCtr.SetRangeMin(0,TRUE);
//m_sliderCtr.SetRangeMin(-100,TRUE);
m_sliderCtr.SetPos(-100);
m_sliderCtr.SetTicFreq(1);
m_slider2.SetRangeMax(255,TRUE);
m_slider2.SetRangeMin(0,TRUE);
m_slider2.SetPos(0);
m_slider2.SetTicFreq(5);
return TRUE; // return TRUE unless you set the focus to a control
}
void CWaveDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
void CWaveDlg::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();
}
}
HCURSOR CWaveDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CWaveDlg::OnStaticWave()
{
// TODO: Add your control notification handler code here
CPoint ptCenter;
::GetCursorPos(&ptCenter);
GetDlgItem(IDC_STATIC_WAVE)->ScreenToClient(&ptCenter);
double radius=5.0;
if (ptCenter.x<0||ptCenter.y<0||ptCenter.x>512||ptCenter.y>512)
{
return;
}
CPoint ptTmp;
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
ptTmp.x=i;
ptTmp.y=j;
if (GetDistance(ptTmp,ptCenter)<=radius)
{
m_pPoolBuff[j*m_nPoolWid+i]=GetEnergyFromWaterSourece(ptCenter,ptTmp,radius,-500);
}
}
}
}
void CWaveDlg::OnButtonTest()
{
}
void CWaveDlg::Shocking()
{
OnStaticWave();
int *pImageBuff=(int*)m_pImageDateBuff;
int *pImageBuff1=(int*)m_pImageDateBuff1;
for (int j=1;j<m_nPoolHei-1;++j)
{
for (int i=1;i<m_nPoolWid-1;++i)
{
int x1=m_pPoolBuff[j*m_nPoolWid+i-1];
int x3=m_pPoolBuff[j*m_nPoolWid+i+1];
int y1=m_pPoolBuff[(j-1)*m_nPoolWid+i];
int y3=m_pPoolBuff[(j+1)*m_nPoolWid+i];
m_pPoolBuff1[j*m_nPoolWid+i]=GetAmplitude(m_pPoolBuff1[j*m_nPoolWid+i],x1,x3,y1,y3);
m_pPoolBuff1[j*m_nPoolWid+i]-=m_pPoolBuff1[j*m_nPoolWid+i]>>7;
int newIndexX=x3-x1+i;
int newIndexY=y3-y1+j;
if (newIndexX>m_nPoolWid)
{
newIndexX=m_nPoolWid;
}
if (newIndexX<0)
{
newIndexX=0;
}
if (newIndexY>m_nPoolHei)
{
newIndexY=m_nPoolHei;
}
if (newIndexY<0)
{
newIndexY=0;
}
pImageBuff1[j*m_nPoolWid+i]=pImageBuff[m_nPoolWid*newIndexY+newIndexX];
}
}
int * pTmp=m_pPoolBuff;
m_pPoolBuff=m_pPoolBuff1;
m_pPoolBuff1=pTmp;
RefreshImag();
}
void CWaveDlg::RefreshImag(void)
{
m_newBmp.SetBitmapBits(m_nPoolWid*m_nPoolHei*4,m_pImageDateBuff1);
CDC memDC;
memDC.CreateCompatibleDC(m_pDC);
CBitmap *pOldBmp=memDC.SelectObject(&m_newBmp);
m_pDC->BitBlt(0,0,m_nPoolWid,m_nPoolHei,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
}
double CWaveDlg::GetDistance(const CPoint & p1,const CPoint &p2)
{
return sqrt((p2.x-p1.x)*(p2.x-p1.x)+(p2.y-p1.y)*(p2.y-p1.y));
}
int CWaveDlg::GetAmplitude(int a0,int a1,int a2,int a3,int a4)
{
int a=((a1+a2+a3+a4)>>1)-a0;
//a-=(a>>5);
return a;
}
int CWaveDlg::GetEnergyFromWaterSourece(const CPoint &ptCenter,const CPoint &pt,double radius,int energy)
{
double dis=GetDistance(ptCenter,pt);
return (int)((1-dis/radius)*energy);
}
void CWaveDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
GetDlgItem(IDC_STATIC_WAVE)->ReleaseDC(m_pDC);
delete [] m_pImageDateBuff;
delete [] m_pImageDateBuff1;
delete [] m_pPoolBuff;
delete [] m_pPoolBuff1;
}
bool m_b=false;
HBRUSH CWaveDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
// TODO: Return a different brush if the default is not desired
return hbr;
}
void CWaveDlg::OnCancelMode()
{
CDialog::OnCancelMode();
// TODO: Add your message handler code here
}
void CWaveDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
Shocking();
CDialog::OnTimer(nIDEvent);
}
void CWaveDlg::OnOK()
{
// TODO: Add extra validation here
// CDialog::OnOK();
//SetTimer(1,40,NULL);
}
void CWaveDlg::OnButton2()
{
// TODO: Add your control notification handler code here
}
void CWaveDlg::AvgChannels(int & r,int &g,int &b)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b1=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
byte g1=m_pImageDateBuff[j*m_nPoolWid*4+i*4+1];
byte r1=m_pImageDateBuff[j*m_nPoolWid*4+i*4+2];
b+=b1;
g+=g1;
r+=r1;
}
}
int count=m_nPoolWid*m_nPoolHei;
b/=count;
g/=count;
r/=count;
}
void CWaveDlg::AdjustContrastAndBrightness(void)
{
//out=avg+(in-avg)*(1+percent);avg=128;
int avgB=0;
int avgG=0;
int avgR=0;
AvgChannels(avgR,avgG,avgB);
for (int j=0;j<m_nPoolHei;++j)
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
byte g=m_pImageDateBuff[j*m_nPoolWid*4+i*4+1];
byte r=m_pImageDateBuff[j*m_nPoolWid*4+i*4+2];
b=avgB+(int)((b-avgB)*(1+m_dbPercent));
g=avgG+(int)((g-avgG)*(1+m_dbPercent));
r=avgR+(int)((r-avgR)*(1+m_dbPercent));
LimitMaxMin(b);
LimitMaxMin(g);
LimitMaxMin(r);
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0]=b;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1]=g;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2]=r;
}
}
RefreshImag();
}
void CWaveDlg::AdjustSimpleContrastAndBrightness(void)
{
int index=0;
int index1=0;
int index2=0;
int index3=0;
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
index=j*(m_nPoolWid<<2)+(i<<2);
index1=index+0;
index2=index+1;
index3=index+2;
byte b=m_pImageDateBuff[index1];
byte g=m_pImageDateBuff[index2];
byte r=m_pImageDateBuff[index3];
b=b*m_dbPercent+m_bBrightness;
g=g*m_dbPercent+m_bBrightness;
r=r*m_dbPercent+m_bBrightness;
LimitMaxMin(b);
LimitMaxMin(g);
LimitMaxMin(r);
m_pImageDateBuff1[index1]=b;
m_pImageDateBuff1[index2]=g;
m_pImageDateBuff1[index3]=r;
}
}
RefreshImag();
}
void CWaveDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
CSliderCtrl *pSlider=(CSliderCtrl *)pScrollBar;
if (pSlider->GetDlgCtrlID()==IDC_SLIDER)
{
m_dbPercent=pSlider->GetPos()*0.01;
}
else if (pSlider->GetDlgCtrlID()==IDC_SLIDER2)
{
m_bBrightness=pSlider->GetPos();
}
//OnMenuitemBinary();
AdjustSimpleContrastAndBrightness();
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CWaveDlg::Rgb2Gray24(int typeFlag)
{
if (typeFlag==0)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0]=b;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1]=b;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2]=b;
//byte g=m_pImageDateBuff[j*m_nPoolWid*4+i*4+1];
//byte r=m_pImageDateBuff[j*m_nPoolWid*4+i*4+2];
}
}
}
else if(typeFlag==1)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
byte g=m_pImageDateBuff[j*m_nPoolWid*4+i*4+1];
byte r=m_pImageDateBuff[j*m_nPoolWid*4+i*4+2];
byte avg=(b+g+r)/3;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0]=avg;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1]=avg;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2]=avg;
}
}
}
else if (typeFlag==2)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
byte g=m_pImageDateBuff[j*m_nPoolWid*4+i*4+1];
byte r=m_pImageDateBuff[j*m_nPoolWid*4+i*4+2];
//byte avg=(b*11+g*59+r*30+50)/100;
byte gray=(r+b+((USHORT)g<<1))>>2;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0]=gray;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1]=gray;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2]=gray;
}
}
}
}
void CWaveDlg::OnMenuitemRgbToGray()
{
// TODO: Add your command handler code here
Rgb2Gray24(2);
RefreshImag();
}
void CWaveDlg::Gray2Binary( byte* imageBuffer,byte threshold)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=imageBuffer[j*m_nPoolWid*4+i*4+0];
if (b>=threshold)
{
b=255;
}
else
{
b=0;
}
imageBuffer[j*m_nPoolWid*4+i*4+0]=b;
imageBuffer[j*m_nPoolWid*4+i*4+1]=b;
imageBuffer[j*m_nPoolWid*4+i*4+2]=b;
}
}
}
void CWaveDlg::OnMenuitemOrgImag()
{
// TODO: Add your command handler code here
memcpy(m_pImageDateBuff1,m_pImageDateBuff,m_nPoolWid*m_nPoolHei*4);
m_newBmp.SetBitmapBits(m_nPoolWid*m_nPoolHei*4,m_pImageDateBuff);
CDC memDC;
memDC.CreateCompatibleDC(m_pDC);
CBitmap *pOldBmp=memDC.SelectObject(&m_newBmp);
m_pDC->BitBlt(0,0,m_nPoolWid,m_nPoolHei,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
}
void CWaveDlg::SaveBmp(void)
{
BITMAPINFO bmpInfo;
memset(&bmpInfo,0,sizeof(BITMAPINFO));
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
bmpInfoHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biBitCount=32;
bmpInfoHeader.biWidth=m_nPoolWid;
bmpInfoHeader.biHeight=m_nPoolHei;
bmpInfoHeader.biPlanes=1;
bmpInfoHeader.biClrImportant=0;
bmpInfoHeader.biClrUsed=0;
bmpInfoHeader.biSizeImage=0;
bmpInfoHeader.biXPelsPerMeter=0;
bmpInfoHeader.biYPelsPerMeter=0;
bmpInfoHeader.biCompression=BI_RGB;
bmpFileHeader.bfType=0x4d42;
bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
bmpFileHeader.bfSize=bmpFileHeader.bfOffBits+m_nPoolHei*m_nPoolWid*4;
bmpFileHeader.bfReserved1=0;
bmpFileHeader.bfReserved2=0;
bmpInfo.bmiHeader=bmpInfoHeader;
CFile file;
file.Open("F:\\work\\Wave\\test.bmp",CFile::modeCreate|CFile::modeWrite);
file.Write(&bmpFileHeader,sizeof(BITMAPFILEHEADER));
file.Write(&bmpInfo,sizeof(BITMAPINFO));
file.Write(m_pImageDateBuff1,m_nPoolWid*m_nPoolHei*4);
file.Close();
}
void CWaveDlg::SaveBmpSingle(void)
{
byte *pBmpBuffer=new byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256];
BITMAPINFO *pbmpInfo=(BITMAPINFO*)(pBmpBuffer);
//memset(&bmpInfo,0,sizeof(BITMAPINFO));
for (int k=0;k<256;k++)
{
pbmpInfo->bmiColors[k].rgbBlue=k;
pbmpInfo->bmiColors[k].rgbGreen=k;
pbmpInfo->bmiColors[k].rgbRed=k;
pbmpInfo->bmiColors[k].rgbReserved=0;
}
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
bmpInfoHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biBitCount=8;
bmpInfoHeader.biWidth=m_nPoolWid;
bmpInfoHeader.biHeight=m_nPoolHei;
bmpInfoHeader.biPlanes=1;
bmpInfoHeader.biClrImportant=0;
bmpInfoHeader.biClrUsed=0;
bmpInfoHeader.biSizeImage=0;
bmpInfoHeader.biXPelsPerMeter=0;
bmpInfoHeader.biYPelsPerMeter=0;
bmpInfoHeader.biCompression=BI_RGB;
bmpFileHeader.bfType=0x4d42;
bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
bmpFileHeader.bfSize=bmpFileHeader.bfOffBits+m_nPoolHei*m_nPoolWid;
bmpFileHeader.bfReserved1=0;
bmpFileHeader.bfReserved2=0;
pbmpInfo->bmiHeader=bmpInfoHeader;
CFile file;
file.Open("F:\\work\\Wave\\test.bmp",CFile::modeCreate|CFile::modeWrite);
file.Write(&bmpFileHeader,sizeof(BITMAPFILEHEADER));
file.Write(pBmpBuffer,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
Rgb2Gray24(2);
byte *pRgbIndex=new byte [m_nPoolWid*m_nPoolHei];
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0];
pRgbIndex[j*m_nPoolWid+i]=b;
}
}
file.Write(pRgbIndex,m_nPoolWid*m_nPoolHei);
file.Close();
delete[]pRgbIndex;
delete[] pBmpBuffer;
}
void CWaveDlg::OnMenuitemBinary()
{
// TODO: Add your command handler code here
Rgb2Gray24(2);
Gray2Binary(m_pImageDateBuff1,m_bBrightness);
RefreshImag();
}
void CWaveDlg::InvertBuffer(INT direction)
{
if (direction==1)//x direction
{
int midWidth=m_nPoolWid/2;
int temp=0;
INT *pImageBuffer=(INT*)m_pImageDateBuff1;
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<midWidth;++i)
{
temp= pImageBuffer[j*m_nPoolWid+i];
pImageBuffer[j*m_nPoolWid+i]=pImageBuffer[j*m_nPoolWid+m_nPoolWid-i-1];
pImageBuffer[j*m_nPoolWid+m_nPoolWid-i-1] =temp;
}
}
}
else if (direction==2)// y direction
{
int temp=0;
int midHeight=m_nPoolHei/2;
INT *pImageBuffer=(INT*)m_pImageDateBuff1;
for (int j=0;j<midHeight;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
temp= pImageBuffer[j*m_nPoolWid+i];
pImageBuffer[j*m_nPoolWid+i]=pImageBuffer[(m_nPoolHei-1-j)*m_nPoolWid+i];
pImageBuffer[(m_nPoolHei-1-j)*m_nPoolWid+i] =temp;
}
}
}
}
void CWaveDlg::OnButtonScrollWnd()
{
// TODO: Add your control notification handler code here
// m_nCount+=5;
// CRect rectClient;
// GetClientRect(&rectClient);
// ::ScrollWindow(GetSafeHwnd(),0,m_nCount,&rectClient,NULL);
}
void CWaveDlg::OnMenuitemInvertY()
{
// TODO: Add your command handler code here
InvertBuffer(2);
RefreshImag();
//SaveBmp();
}
void CWaveDlg::OnMenuitemInvertX()
{
// TODO: Add your command handler code here
InvertBuffer(1);
RefreshImag();
}
void CWaveDlg::RoateImag(CPoint & roatePos,double roateAngle)
{
}
void CWaveDlg::GetHistogram(int *Histo)
{
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0];
Histo[b]++;
}
}
}
void CWaveDlg::OnMenuitemHisto()
{
// TODO: Add your command handler code here
INT histo[256];
memset(histo,0,256*sizeof(INT));
Rgb2Gray24(1);
GetHistogram(histo);
DrawHistoGram(histo);
}
void CWaveDlg::DrawHistoGram(int *Histo)
{
m_newBmp.SetBitmapBits(m_nPoolWid*m_nPoolHei*4,m_pImageDateBuff1);
CDC memDC;
memDC.CreateCompatibleDC(m_pDC);
CBitmap *pOldBmp=memDC.SelectObject(&m_newBmp);
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen* pOldPen=memDC.SelectObject(&pen);
CPoint ptCord(50,m_nPoolHei-50);//坐标原点
//画x轴
memDC.MoveTo(ptCord.x,ptCord.y);
memDC.LineTo(m_nPoolWid,ptCord.y);
//画刻度
//memDC.MoveTo(ptCord.x,ptCord.y);
for (int x=ptCord.x;x<ptCord.x+256;x++)
{
memDC.MoveTo(x,ptCord.y);
memDC.LineTo(x,ptCord.y-Histo[x-ptCord.x]/15);
}
//画y轴
memDC.MoveTo(ptCord.x,ptCord.y);
memDC.LineTo(ptCord.x,0);
m_pDC->BitBlt(0,0,m_nPoolWid,m_nPoolHei,&memDC,0,0,SRCCOPY);
memDC.SelectObject(pOldBmp);
memDC.SelectObject(&pOldPen);
memDC.DeleteDC();
}
void CWaveDlg::Rgb2Gray8(void)
{
}
void CWaveDlg::Rgb2Gray16(void)
{
}
void CWaveDlg::Rgb2Rgb8(void)
{
}
void CWaveDlg::Rgb2Rgb16(void)
{
}
void CWaveDlg::OnMenuitemSaveGray8bit()
{
// TODO: Add your command handler code here
SaveBmpSingle();
}
void CWaveDlg::SaveBmpBinary(void)
{
byte *pBmpBuffer=new byte[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2];
BITMAPINFO *pbmpInfo=(BITMAPINFO*)(pBmpBuffer);
//memset(&bmpInfo,0,sizeof(BITMAPINFO));
for (int k=0;k<2;k++)
{
pbmpInfo->bmiColors[k].rgbBlue=k*255;
pbmpInfo->bmiColors[k].rgbGreen=k*255;
pbmpInfo->bmiColors[k].rgbRed=k*255;
pbmpInfo->bmiColors[k].rgbReserved=0;
}
BITMAPFILEHEADER bmpFileHeader;
BITMAPINFOHEADER bmpInfoHeader;
bmpInfoHeader.biSize=sizeof(BITMAPINFOHEADER);
bmpInfoHeader.biBitCount=1;
bmpInfoHeader.biWidth=m_nPoolWid;
bmpInfoHeader.biHeight=-m_nPoolHei;
bmpInfoHeader.biPlanes=1;
bmpInfoHeader.biClrImportant=0;
bmpInfoHeader.biClrUsed=0;
bmpInfoHeader.biSizeImage=0;
bmpInfoHeader.biXPelsPerMeter=0;
bmpInfoHeader.biYPelsPerMeter=0;
bmpInfoHeader.biCompression=BI_RGB;
bmpFileHeader.bfType=0x4d42;
bmpFileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2;
bmpFileHeader.bfSize=bmpFileHeader.bfOffBits+m_nPoolHei*m_nPoolWid;
bmpFileHeader.bfReserved1=0;
bmpFileHeader.bfReserved2=0;
pbmpInfo->bmiHeader=bmpInfoHeader;
CFile file;
file.Open("F:\\work\\Wave\\test.bmp",CFile::modeCreate|CFile::modeWrite);
file.Write(&bmpFileHeader,sizeof(BITMAPFILEHEADER));
file.Write(pBmpBuffer,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2);
Rgb2Gray24(2);
byte shiftX=0x01;
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0];
int k=(j*m_nPoolWid+i+1)%8;
}
}
// file.Write(pRgbIndex,m_nPoolWid*m_nPoolHei/8);
file.Close();
delete[] pBmpBuffer;
}
void CWaveDlg::OnMenuitemSaveBinaryBmp1bit()
{
// TODO: Add your command handler code here
SaveBmpBinary();
}
void CWaveDlg::OnMenuitemGlobGrayStretch()
{
// TODO: Add your command handler code here
GlobGrayStrench();
}
void CWaveDlg::HistogramEqualization(void)
{
INT histo[256];
double pHisto[256];
memset(histo,0,256*sizeof(INT));
memset(pHisto,0,256*sizeof(double));
Rgb2Gray24(1);
GetHistogram(histo);
int count=m_nPoolHei*m_nPoolWid;
for (int ii=0;ii<256;++ii)
{
pHisto[ii]=histo[ii]/(double)count;
}
CalculateCDF(pHisto);
for (int j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff[j*m_nPoolWid*4+i*4+0];
byte bValue=(byte)(pHisto[b]*255.0);
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0]=bValue;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1]=bValue;
m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2]=bValue;
}
}
GetHistogram(histo);
DrawHistoGram(histo);
}
void CWaveDlg::CalculateCDF(double *p)
{
for (int i=0;i<256;++i)
{
for (int k=0;k<=i;++k)
{
p[i]+=p[k];
}
}
}
void CWaveDlg::GlobGrayStrench()
{
INT histo[256];
memset(histo,0,256*sizeof(INT));
Rgb2Gray24(1);
byte max=0,min=0;
INT j;
for ( j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte b=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0];
if (b>=max)
{
max=b;
}
if (b<=min)
{
min=b;
}
}
}
byte d=max-min;
for ( j=0;j<m_nPoolHei;++j)
{
for (int i=0;i<m_nPoolWid;++i)
{
byte &b=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+0];
byte &g=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+1];
byte &r=m_pImageDateBuff1[j*m_nPoolWid*4+i*4+2];
b=(byte)((b-min)*(255.0/d));
g=(byte)((g-min)*(255.0/d));
r=(byte)((r-min)*(255.0/d));
}
}
GetHistogram(histo);
DrawHistoGram(histo);
}
void CWaveDlg::OnMenuitemHistoEqualization()
{
// TODO: Add your command handler code here
HistogramEqualization();
}
5-3 直方图均衡化
#灰度 直方图均衡化
import cv2
import numpy as np
img = cv2.imread(''image0.jpg'',1)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow(''src'',gray)
dst = cv2.equalizeHist(gray)
cv2.imshow(''dst'',dst)
cv2.waitKey(0)
我们使用直方图均衡化的时候,必须要对单通道进行处理。所以我们首先要完成通道的分解。我们要把原来的三通道分解成单通道。
split()方法。将彩色图片传递进去之后,它返回的就是一个三通道数据。我们分别把三通道数据为大家实现一下。
这样我们分别就有三个通道完成了直方图的均衡化。但是通道分解完之后我们要合并在一起。
经过直方图均衡化之后,整个图片的颜色发生了一定的变化。这是彩色图片均衡化。
#彩色 直方图均衡化
import cv2
import numpy as np
img = cv2.imread(''image0.jpg'',1)
#gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow(''src'',img)
(b,g,r) = cv2.split(img)# 通道分解
bH = cv2.equalizeHist(b)#bH定义的是b通道的直方图均衡化之后的结果,我们将b通道的数据传递进去
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
result = cv2.merge((bH,gH,rH))#merge()方法是opencv自带的 通道合成
#dst = cv2.equalizeHist(gray)
#cv2.imshow(''dst'',dst)
cv2.imshow(''dst'',result)
cv2.waitKey(0)
图片读取进来之后我们要进行YUV的分解。这个cvt方法不光能实现彩色图片转化为灰度图片,还可以实现RGB图片转化为当前的YUV图片。
YUV同样是由三个元素组成。它是一个三维的。我们首先把第一维获取出来,第一维的结果我们先把它进行直方图的均衡化一下。
均衡化之后我们把当前的YUV三个通道再进行合成,合成一个channels。合成之后我们需要把当前的YUV再转成BGR图片。
#YUV 直方图均衡化
import cv2
import numpy as np
img = cv2.imread(''image0.jpg'',1)
#gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
imgYUV = cv2.cvtColor(img,cv2.COLOR_BGR2YCrCb)
#cv2.imshow(''src'',gray)
cv2.imshow(''src'',img)
channelYUV = cv2.split(imgYUV)
channelYUV[0] = cv2.equalizeHist(channelYUV[0])
#dst = cv2.equalizeHist(gray)
channels = cv2.merge(channelYUV)
result = cv2.cvtColor(channels,cv2.COLOR_YCrCb2BGR)
#cv2.imshow(''dst'',dst)
cv2.imshow(''dst'',result)
cv2.waitKey(0)
c#数字图像处理(五)全等级直方图灰度拉伸
灰度拉伸也属于线性点运算的一种,也可以通过上一节的程序得到。但由于它在点运算的特殊性,所以把它单独列出来进行介绍。
灰度拉伸定义
如果一幅图像的灰度值分布在全等级灰度范围内,即在0~255之间,那么它更容易被区别确认出来。
灰度拉伸,也称对比度拉伸,是一种简单的线性点运算。它扩展图像的直方图,使其充满整个灰度等级范围内。
设f(x,y)为输入图像,它的最小灰度级A和最大灰度级B的定义为:
A=min[f(x,y) B=max[f(x,y)]
我们的目标是按照公式 g(x, y)=pf(x,y)+L , 把A和B分别线性映射到0和255,因此,最终的图像g(x,y)为:
private void stretch_Click(object sender, EventArgs e)
{
Stretch(curBitmpap, out curBitmpap);
Invalidate();
}
/// <summary>
/// 全等级灰度拉伸 (图像增强)
/// </summary>
/// <param name="srcBmp">原图像</param>
/// <param name="dstBmp">处理后图像</param>
/// <returns>处理成功 true 失败 false</returns>
public static bool Stretch(Bitmap srcBmp, out Bitmap dstBmp)
{
if (srcBmp == null)
{
dstBmp = null;
return false;
}
double pR = 0.0;//斜率
double pG = 0.0;//斜率
double pB = 0.0;//斜率
byte minGrayDegree = 255;
byte maxGrayDegree = 0;
byte minGrayDegreeR = 255;
byte maxGrayDegreeR = 0;
byte minGrayDegreeG = 255;
byte maxGrayDegreeG = 0;
byte minGrayDegreeB = 255;
byte maxGrayDegreeB = 0;
dstBmp = new Bitmap(srcBmp);
Rectangle rt = new Rectangle(0, 0, dstBmp.Width, dstBmp.Height);
BitmapData bmpData = dstBmp.LockBits(rt, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
for (int i = 0; i < bmpData.Height; i++)
{
byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < bmpData.Width; j++)
{
if (minGrayDegreeR > *(ptr + j * 3 + 2))
minGrayDegreeR = *(ptr + j * 3 + 2);
if (maxGrayDegreeR < *(ptr + j * 3 + 2))
maxGrayDegreeR = *(ptr + j * 3 + 2);
if (minGrayDegreeG > *(ptr + j * 3 + 1))
minGrayDegreeG = *(ptr + j * 3 + 1);
if (maxGrayDegreeG < *(ptr + j * 3 + 1))
maxGrayDegreeG = *(ptr + j * 3 + 1);
if (minGrayDegreeB > *(ptr + j * 3))
minGrayDegreeB = *(ptr + j * 3);
if (maxGrayDegreeB < *(ptr + j * 3))
maxGrayDegreeB = *(ptr + j * 3);
}
}
pR = 255.0 / (maxGrayDegreeR - minGrayDegreeR);
pG = 255.0 / (maxGrayDegreeG - minGrayDegreeG);
pB = 255.0 / (maxGrayDegreeB - minGrayDegreeB);
for (int i = 0; i < bmpData.Height; i++)
{
byte* ptr1 = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < bmpData.Width; j++)
{
*(ptr1 + j * 3) = (byte)((*(ptr1 + j * 3) - minGrayDegreeB) * pB + 0.5);
*(ptr1 + j * 3 + 1) = (byte)((*(ptr1 + j * 3 + 1) - minGrayDegreeG) * pG + 0.5);
*(ptr1 + j * 3 + 2) = (byte)((*(ptr1 + j * 3 + 2) - minGrayDegreeR) * pR + 0.5);
}
}
}
dstBmp.UnlockBits(bmpData);
return true;
}
增强后:
c#数字图像处理(六)直方图均衡化
直方图均衡化又称直方图修平,是一种很重要的非线性点运算。使用该方法可以加强图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好的在直方图上分布。
直方图均衡化的基本思想是把原始图像的直方图变换为均匀分布的形式。这样增加了灰度值的动态范围,从而达到增强图像整体对比度的效果。
算法步骤:
1)计算图像f(x,y)的各灰度级中像素出现的概率p(i)。
2) 计算p的累计概率函数c(i),c即为图像的累计归一化直方图
3)将c(i)缩放至0~255范围内
/// <summary>
/// 直方图均衡化 直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同
/// 增大对比度,从而达到图像增强的目的。是图像处理领域中利用图像直方图对对比度进行调整的方法
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="dstBmp">处理后图像</param>
/// <returns>处理成功 true 失败 false</returns>
public static bool Balance(Bitmap srcBmp, out Bitmap dstBmp) {
if (srcBmp == null) {
dstBmp = null;
return false;
}
int[] histogramArrayR = new int[256];//各个灰度级的像素数R
int[] histogramArrayG = new int[256];//各个灰度级的像素数G
int[] histogramArrayB = new int[256];//各个灰度级的像素数B
int[] tempArrayR = new int[256];
int[] tempArrayG = new int[256];
int[] tempArrayB = new int[256];
byte[] pixelMapR = new byte[256];
byte[] pixelMapG = new byte[256];
byte[] pixelMapB = new byte[256];
dstBmp = new Bitmap(srcBmp);
Rectangle rt = new Rectangle(0, 0, srcBmp.Width, srcBmp.Height);
BitmapData bmpData = dstBmp.LockBits(rt, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe {
//统计各个灰度级的像素个数
for (int i = 0; i < bmpData.Height; i++) {
byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < bmpData.Width; j++) {
histogramArrayB[*(ptr + j * 3)]++;
histogramArrayG[*(ptr + j * 3 + 1)]++;
histogramArrayR[*(ptr + j * 3 + 2)]++;
}
}
//计算各个灰度级的累计分布函数
for (int i = 0; i < 256; i++) {
if (i != 0) {
tempArrayB[i] = tempArrayB[i - 1] + histogramArrayB[i];
tempArrayG[i] = tempArrayG[i - 1] + histogramArrayG[i];
tempArrayR[i] = tempArrayR[i - 1] + histogramArrayR[i];
}
else {
tempArrayB[0] = histogramArrayB[0];
tempArrayG[0] = histogramArrayG[0];
tempArrayR[0] = histogramArrayR[0];
}
//计算累计概率函数,并将值放缩至0~255范围内
pixelMapB[i] = (byte)(255.0 * tempArrayB[i] / (bmpData.Width * bmpData.Height) + 0.5);//加0.5为了四舍五入取整
pixelMapG[i] = (byte)(255.0 * tempArrayG[i] / (bmpData.Width * bmpData.Height) + 0.5);
pixelMapR[i] = (byte)(255.0 * tempArrayR[i] / (bmpData.Width * bmpData.Height) + 0.5);
}
//映射转换
for (int i = 0; i < bmpData.Height; i++) {
byte* ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < bmpData.Width; j++) {
*(ptr + j * 3) = pixelMapB[*(ptr + j * 3)];
*(ptr + j * 3 + 1) = pixelMapG[*(ptr + j * 3 + 1)];
*(ptr + j * 3 + 2) = pixelMapR[*(ptr + j * 3 + 2)];
}
}
}
dstBmp.UnlockBits(bmpData);
return true;
}
C语言实现BMP图像处理(直方图均衡化)
本文实例为大家分享了C语言实现BMP图像直方图均衡化处理的具体代码,供大家参考,具体内容如下
计算步骤:
1)统计各灰度值的概率;
2)计算了累积概率直方图(CDF);
3)取整扩展:Tk = int[ (L-1)*Tk];
#include <Windows.h> #include <stdlib.h> #include <stdio.h> #include <math.h> int main(int* argc, char** argv) { FILE* fp = fopen("./01.bmp", "rb"); if (fp == 0) return 0; BITMAPFILEHEADER fileHead; fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp); BITMAPINFOHEADER infoHead; fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp); int width = infoHead.biWidth; int height = infoHead.biHeight; int biCount = infoHead.biBitCount; int lineByte = (biCount*width / 8 + 3) / 4 * 4; RGBQUAD* pColorTable; pColorTable = new RGBQUAD[256]; fread(pColorTable, sizeof(RGBQUAD), 256, fp); unsigned char* pBmpBuf; pBmpBuf = new unsigned char[lineByte*height]; fread(pBmpBuf, lineByte*height, 1, fp); fclose(fp); // 统计概率 double st[256] = { 0 }; int st1[256] = { 0 }; int t; for (int i = 0; i < height; ++i){ for (int j = 0; j < width; ++j){ t = *(pBmpBuf + i*lineByte + j); st[t]++; } } // 计算累加直方图并完成映射 st[0] = st[0] / (width*height); st1[0] = round(double((256 - 1)*st[0])); for (int i = 1; i < 256; ++i){ st[i] = st[i] / (width*height); st[i] = st[i] + st[i - 1]; st1[i] = int(round(double((256 - 1)*st[i]))); printf("st[i] = %d, st1[t] = %d\n", st[i], st1[i]); } // 新图像的像素填充 unsigned char* pBmpBuf1; pBmpBuf1 = new unsigned char[lineByte*height]; for (int i = 0; i < height; ++i){ for (int j = 0; j < width; ++j){ t = *(pBmpBuf + i*lineByte + j); *(pBmpBuf1 + i*lineByte + j) = st1[t]; } } FILE* fop = fopen("./imhist.bmp", "wb"); if (fop == 0) return 0; fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fop); fwrite(&infoHead, sizeof(BITMAPINFOHEADER), 1, fop); fwrite(pColorTable, sizeof(RGBQUAD), 256, fop); fwrite(pBmpBuf1, lineByte*height, 1, fop); fclose(fop); system("pause"); return 0; }
实验结果:
实验结果分析:对比原图与实验结果图,原图中,头发和衣领处灰度值较低的地方在结果图中灰度值更低,而原图中,额头中间偏右处较亮,在结果图中更亮,灰度值更大。整体上直方图均衡化拉伸了全局对比度。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- C语言数字图像处理之图像缩放
- C语言数字图像处理之直方图均衡化
- C语言实现BMP图像处理(彩色图转灰度图)
- C语言实现BMP图像处理(哈夫曼编码)
- C语言实现BMP图像开运算处理
关于bmp位图保存方法、灰度拉伸、直方图均衡化和水波纹模拟和bmp 位图的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于5-3 直方图均衡化、c#数字图像处理(五)全等级直方图灰度拉伸、c#数字图像处理(六)直方图均衡化、C语言实现BMP图像处理(直方图均衡化)的相关知识,请在本站寻找。
本文标签: