2012-09-20 11:43:30 rabbit729 阅读数 5514
  • Tensorflow-图像处理视频教程

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 课程以图像处理软件Tensorflow作为核心武器,基于图像处理热点话题进行案例实战。选择当下热门模型,使用真实数据集进行实战演示,通俗讲解整个算法模型并使用tensorflow进行实战,详解其中的原理与代码实现。

    1241 人正在学习 去看看 唐宇迪

  本系列文章将使用GPU实现图像处理中常用的算法,此处只给出代码,关于算法原理描述有很多资料,大家可以自行查找。不足之处请大家不吝赐教,共同提高。

/********************************
*  Author: rabbit729
*  E-mail: wlq_729@163.com
*  Date:   2012-09-20
*  Description: 图像的二值化
********************************/
#include <d3dx9.h>

//-----------------------------------------------------------------------------
// Desc: 全局变量
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D                 = NULL;  //Direct3D对象
LPDIRECT3DDEVICE9       g_pd3dDevice           = NULL;  //Direct3D设备对象

LPDIRECT3DTEXTURE9      g_pTextureScreen        = NULL; //待处理图片

ID3DXEffect*            g_pEffect               = NULL;  //效果指针
//常量句柄
D3DXHANDLE              hTechScreen             = NULL;  //Effect句柄
D3DXHANDLE              hTexScreen              = NULL;  //纹理句柄
D3DXHANDLE              hViewPortWidthInv       = NULL;  //视口宽倒数句柄
D3DXHANDLE              hViewPortHeightInv      = NULL;  //视口高倒数句柄

LPDIRECT3DVERTEXBUFFER9 g_pScreenSpaceQuad      = NULL;  //背板VB

const int WIDTH  = 465;
const int HEIGHT = 669;

#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)

struct Vertex
{
	Vertex(){}
	Vertex(float x, float y, float z, float w)
	{
		_x = x;   _y = y;   _z = z; _w = w;
	}

	float _x, _y, _z, _w;

	static const DWORD FVF;
};
const DWORD Vertex::FVF = D3DFVF_XYZW;


//-----------------------------------------------------------------------------
// Desc: 设置世界矩阵
//-----------------------------------------------------------------------------
VOID SetWorldMatrix()
{
	//创建并设置世界矩阵
	D3DXMATRIXA16 matWorld, matRotateX, matRotateY;
	D3DXMATRIXA16 matScale;
	D3DXMatrixIdentity(&matScale);
	matScale._11 = matScale._22 = matScale._33 = 0.5f;

	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixIdentity(&matRotateX);
	D3DXMatrixIdentity(&matRotateY);
	D3DXMatrixRotationX( &matRotateX, D3DX_PI / 3.0 );
	D3DXMatrixRotationY( &matRotateY, -D3DX_PI / 8.0 );
	D3DXMatrixMultiply(&matWorld, &matRotateX, &matRotateY);

	D3DXMatrixMultiply(&matWorld, &matScale, &matWorld);
	g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
}


//-----------------------------------------------------------------------------
// Desc: 设置观察矩阵和投影矩阵
//-----------------------------------------------------------------------------
VOID SetViewAndProjMatrix()
{
	//创建并设置观察矩阵
	D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-250.0f );
	D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
	D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
	g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

	//创建并设置投影矩阵
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 1000.0f );
	g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}


//-----------------------------------------------------------------------------
// Desc: 初始化Direct3D
//-----------------------------------------------------------------------------
HRESULT InitD3D( HWND hWnd )
{
	//创建Direct3D对象, 该对象用于创建Direct3D设备对象
	if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
		return E_FAIL;

	//设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象
	D3DPRESENT_PARAMETERS d3dpp; 
	ZeroMemory( &d3dpp, sizeof(d3dpp) );
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;

	//创建Direct3D设备对象
	if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
		&d3dpp, &g_pd3dDevice ) ) )
	{
		return E_FAIL;
	}

	//创建Effect
	ID3DXBuffer* errBuffer = NULL;
	if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, L"erzhihua.fx", NULL, NULL, D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION, NULL, &g_pEffect, &errBuffer)))
	{
		if (errBuffer)
		{
			MessageBox(0, (LPCTSTR)errBuffer->GetBufferPointer(), 0, 0);
			errBuffer->Release();
		}
		return E_FAIL;
	}

	//获取常量句柄
	hTechScreen         = g_pEffect->GetTechniqueByName("Screen");
	hTexScreen          = g_pEffect->GetParameterByName(0, "TexScreen");
	hViewPortWidthInv   = g_pEffect->GetParameterByName(0, "viewport_inv_width");
	hViewPortHeightInv  = g_pEffect->GetParameterByName(0, "viewport_inv_height");

	//设置环境光
	g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xffffffff );

	//设置观察矩阵和投影矩阵
	SetViewAndProjMatrix();

	return S_OK;
}

//-----------------------------------------------------------------------------
// Desc: 创建场景图形
//-----------------------------------------------------------------------------
HRESULT InitGeometry()
{
	// 创建屏幕板
	g_pd3dDevice->CreateVertexBuffer(
		6 * sizeof(Vertex),
		D3DUSAGE_WRITEONLY,
		Vertex::FVF, 
		D3DPOOL_MANAGED,
		&g_pScreenSpaceQuad,
		0);

	Vertex* vertices;
	g_pScreenSpaceQuad->Lock(0, 0, (void**)&vertices, 0);

	vertices[0] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);
	vertices[1] = Vertex(1.0f,  1.0f, 0.5f, 1.0f);
	vertices[2] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);
	vertices[3] = Vertex(-1.0f, 1.0f, 0.5f, 1.0f);
	vertices[4] = Vertex( 1.0f, -1.0f, 0.5f, 1.0f);
	vertices[5] = Vertex( -1.0f, -1.0f, 0.5f, 1.0f);

	g_pScreenSpaceQuad->Unlock();

	//加载纹理
	HRESULT hr = D3DXCreateTextureFromFile(g_pd3dDevice, L"meinv.jpg", &g_pTextureScreen);
	if (FAILED(hr))
	{
		return E_FAIL;
	} 

	return S_OK;
}


//-----------------------------------------------------------------------------
// Desc: 释放创建的对象
//-----------------------------------------------------------------------------
VOID Cleanup()
{
	if (g_pScreenSpaceQuad != NULL)
	{
		g_pScreenSpaceQuad->Release();
	}

	if (g_pTextureScreen != NULL)
	{
		g_pTextureScreen->Release();
	}

	if (g_pEffect != NULL)
	{
		g_pEffect->Release();
	}

	//释放Direct3D设备对象
	if( g_pd3dDevice != NULL )
		g_pd3dDevice->Release();

	//释放Direct3D对象
	if( g_pD3D != NULL )
		g_pD3D->Release();
}

VOID RenderScreen()
{
	//将RenderTarget作为纹理
	g_pEffect->SetTexture(hTexScreen, g_pTextureScreen);

	float fWidthInv = 1.0f / WIDTH;
	float fHeightInv = 1.0f / HEIGHT;
	g_pEffect->SetFloat(hViewPortWidthInv, fWidthInv);
	g_pEffect->SetFloat(hViewPortHeightInv, fHeightInv);

	g_pd3dDevice->SetStreamSource(0, g_pScreenSpaceQuad, 0, sizeof(Vertex));
	g_pd3dDevice->SetFVF(Vertex::FVF);

	// 设置要使用的Technique
	g_pEffect->SetTechnique(hTechScreen);

	UINT numPasses = 0;
	g_pEffect->Begin(&numPasses, 0);

	for (int i = 0; i < numPasses; i++)
	{
		g_pEffect->BeginPass(i);

		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

		g_pEffect->EndPass();
	}
	g_pEffect->End();
}

//-----------------------------------------------------------------------------
// Desc: 渲染场景
//-----------------------------------------------------------------------------
VOID Render()
{    
	// 获取backbuffer
	LPDIRECT3DSURFACE9 pBackbuffer;
	g_pd3dDevice->GetRenderTarget(0, &pBackbuffer);

	//开始渲染场景
	if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
	{
		//设回backbuffer
		g_pd3dDevice->SetRenderTarget(0, pBackbuffer);
		RenderScreen();

		//场景渲染结束
		g_pd3dDevice->EndScene();
	}

	//在屏幕上显示场景
	g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}


//-----------------------------------------------------------------------------
// Desc: 窗口过程, 处理消息
//-----------------------------------------------------------------------------
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_DESTROY:
		Cleanup();
		PostQuitMessage( 0 );
		return 0;
	}

	return DefWindowProc( hWnd, msg, wParam, lParam );
}


//-----------------------------------------------------------------------------
// Desc: 入口函数
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
	//注册窗口类
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
		GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
		L"ClassName", NULL };
	RegisterClassEx( &wc );

	//创建窗口
	HWND hWnd = CreateWindow( L"ClassName", L"图像二值化", 
		WS_OVERLAPPEDWINDOW, 200, 100, WIDTH, HEIGHT,
		GetDesktopWindow(), NULL, wc.hInstance, NULL );

	//初始化Direct3D
	if( SUCCEEDED( InitD3D( hWnd ) ) )
	{ 
		//创建场景图形
		if( SUCCEEDED( InitGeometry() ) )
		{
			//显示窗口
			ShowWindow( hWnd, SW_SHOWDEFAULT );
			UpdateWindow( hWnd );

			//进入消息循环
			MSG msg; 
			ZeroMemory( &msg, sizeof(msg) );
			while( msg.message!=WM_QUIT )
			{
				if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
				{
					TranslateMessage( &msg );
					DispatchMessage( &msg );
				}
				else
				{
					Render();  //渲染场景
				}
			}
		}
	}

	UnregisterClass( L"ClassName", wc.hInstance );
	return 0;
}


Effect代码如下:

/********************************
*  Author: rabbit729
*  E-mail: wlq_729@163.com
*  Date:   2011-09-20
********************************/

//------------------------------
//  顶点着色器
//------------------------------

float viewport_inv_width;
float viewport_inv_height;
struct VS_OUTPUTSCREEN {
   float4 Pos: POSITION;
   float2 texCoord: TEXCOORD0;
};

VS_OUTPUTSCREEN vs_mainPassScreen(float4 Pos: POSITION){
   VS_OUTPUTSCREEN Out;

   Out.Pos = float4(Pos.xy, 0, 1);

   Out.texCoord.x = 0.5 * (1 + Pos.x - viewport_inv_width);
   Out.texCoord.y = 0.5 * (1 - Pos.y - viewport_inv_height);

   return Out;
}

//------------------------------
//  像素着色器
//------------------------------
Texture2D TexScreen;

sampler2D TexMapScreen {
    Texture = <TexScreen>;
};

float4 ps_mainPassScreen(float2 texCoord: TEXCOORD0) : COLOR 
{
   float4 col = tex2D(TexMapScreen,  texCoord);
   float Intensity;

   // 灰度化
   // I = 0.299*R + 0.587*G + 0.184*B
   Intensity = 0.299*col.r + 0.587*col.g + 0.184*col.r;
   
   // 阈值为0.5,关于怎么选取阈值有好多方法,大家可以自行查阅
   if(Intensity > 0.5)
      Intensity = 0.5f;
   else
      Intensity = 0.1f;

   return float4(Intensity.xxx,col.a);
}

technique Screen
{
   pass P0
   {
      VertexShader = compile vs_3_0 vs_mainPassScreen();
      PixelShader  = compile ps_3_0 ps_mainPassScreen();
   }
}


 结果:

原始图片:

二值化后结果:

2010-05-10 09:17:00 xelone 阅读数 777
  • Tensorflow-图像处理视频教程

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 课程以图像处理软件Tensorflow作为核心武器,基于图像处理热点话题进行案例实战。选择当下热门模型,使用真实数据集进行实战演示,通俗讲解整个算法模型并使用tensorflow进行实战,详解其中的原理与代码实现。

    1241 人正在学习 去看看 唐宇迪

  图像处理常用算法 收藏
/***************************************************************/
/*函数名称:MakegGray()                                        */
/*函数类型:void                                               */
/*功能:真彩色转化成256色灰度图像。                            */
/***************************************************************/
void MakeColorDib::MakegGray()    //灰度变化
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();   //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i+=3) // 每列
  {
   BYTE* pbyBlue = p_data++;   //得到蓝色值
   BYTE* pbyGreen = p_data++;  //得到绿色值
   BYTE* pbyRed = p_data++;    //得到红色值
   BYTE r = *pbyRed;
   BYTE g = *pbyGreen;
   BYTE b = *pbyBlue;
   //取到原r,g,b中的最大值作为像素三分量值的新值
   int gray=0;
   if(r>g)
    gray=r;
   else
    gray=g;
   if(gray<b)
    gray=b;  
         *pbyBlue = gray;     //将取到的最大值赋给像素的蓝分量
   *pbyGreen = gray;    //将取到的最大值赋给像素的绿分量
   *pbyRed = gray;      //将取到的最大值赋给像素的红分量
  }
}

/***************************************************************/
/*函数名称:LightAlter(int m_Light)                            */
/*函数类型:void                                               */
/*参数:int m_Light,用户给定的阈值                            */
/*功能:对图像使用阈值法进行亮度调整。                         */
/***************************************************************/
void MakeColorDib::LightAlter(int m_Light)    //亮度调整
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();    //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
 for(int i=0;i<DibWidth;i++) // 每列
 {  
  int a=0;
  a=int(*p_data*m_Light/100);   //调整当前点的亮度
  *p_data=a;
  //判断范围,取得合理的值
  if(a<0)
   *p_data=0; 
     if(a>255)
   *p_data=255;
        p_data++;   //指向下一指针
 }
}

/***************************************************************/
/*函数名称:LightReverse()                                     */
/*函数类型:void                                               */
/*功能:图像的亮度取反。                                       */
/***************************************************************/
void MakeColorDib::LightReverse()    //亮度取反
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i++) // 每列
  {
   int a=*p_data;   //取得当前点的值
   *p_data=255-a;    //取反
   p_data++;  //指向下一指针 
  }
}

/***************************************************************/
/*函数名称:ContrastAlter(int m_Increment)                     */
/*函数类型:void                                               */
/*参数:int m_Increment,用户给定的阈值                        */
/*功能:对图像使用阈值法调整对比度处理。                       */
/***************************************************************/
void MakeColorDib::ContrastAlter(int m_Increment)   ///对比度处理
{
 int nHigh = 255 - m_Increment;
 //对于极端情况加以处理
 if(nHigh < m_Increment)
 {
  nHigh = 127;
  m_Increment = 120;
 }
 if(m_Increment < -127)
  m_Increment = -120;
 //扩展或压缩区间的长度
 int nStretch = 255;
 if(m_Increment >= 0)
  nStretch = 255 - 2 * m_Increment;
 else
  nStretch = 255 + 2 * m_Increment;
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 if(m_Increment >= 0)   // m_Increment>=0时
 {
  for(int j=0;j<height;j++) // 每行
   for(int i=0;i<DibWidth-3;i+=3) // 每列
   {  
    //取得当前点(蓝色)的值,调整
    BYTE* pbyBlue = p_data++;   
    if(*pbyBlue<=m_Increment)
     *pbyBlue=0;
    else if(*pbyBlue>nHigh)
     *pbyBlue=255;
    else
     *pbyBlue=(BYTE)((((int)*pbyBlue - m_Increment) * 255) / nStretch );
    //取得当前点(绿色)的值,调整
    BYTE* pbyGreen = p_data++;
    if(*pbyGreen<=m_Increment)
     *pbyGreen=0;
    else if(*pbyGreen>nHigh)
     *pbyGreen=255;
    else
     *pbyGreen=(BYTE)((((int)*pbyGreen - m_Increment) * 255) / nStretch );
    //取得当前点(红色)的值,调整
    BYTE* pbyRed = p_data++;
    if(*pbyRed<=m_Increment)
     *pbyRed=0;
    else if(*pbyRed>nHigh)
     *pbyRed=255;
    else
     *pbyRed=(BYTE)((((int)*pbyRed - m_Increment) * 255) / nStretch );
   }
  
 }
 else  // m_Increment < 0 时
 {
  for(int j=0;j<height;j++)
   for(int i=0;i<DibWidth-3;i+=3)
   { //取得当前点(蓝色)的值,调整
    BYTE* pbyBlue = p_data++;
    *pbyBlue = (BYTE)((((int)(*pbyBlue) * nStretch) / 255) - m_Increment);
    //取得当前点(红色)的值,调整
    BYTE* pbyGreen = p_data++;
    *pbyGreen = (BYTE)((((int)(*pbyGreen) * nStretch) / 255) - m_Increment);
    //取得当前点(红色)的值,调整
    BYTE* pbyRed = p_data++;
    *pbyRed = (BYTE)((((int)(*pbyRed) * nStretch) / 255) - m_Increment);   
   }
 }
}

/***************************************************************/
/*函数名称:Exposal()                                          */
/*函数类型:void                                               */
/*功能:图像曝光处理。                                         */
/***************************************************************/
void MakeColorDib::Exposal() //曝光处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i++) // 每列
  {
   BYTE* pbydata = p_data++;  //取得当前点的值
   BYTE a=*pbydata;   //传给临时变量
   *pbydata=(a>128)?a:(255-a);   //调整
  }
 
}

/***************************************************************/
/*函数名称:PaintColor(int m_Red,int m_Green,int m_Blue)       */
/*函数类型:void                                               */
/*参数:int m_Red、m_Green、m_Blue,用户给定的红绿蓝值         */
/*功能:对图像使用阈值法进行着色处理。                         */
/***************************************************************/
void MakeColorDib::PaintColor(int m_Red,int m_Green,int m_Blue) //着色处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 for(int j=0;j<height;j++) // 每行
  for(int i=0;i<DibWidth;i+=3) // 每列
  {  
   BYTE* pbyBlue = p_data++; //取得当前点(蓝色)的值    
   BYTE* pbyGreen = p_data++;  //取得当前点(绿色)的值
   BYTE* pbyRed = p_data++;    //取得当前点(红色)的值
   BYTE r = *pbyRed;
   BYTE g = *pbyGreen;
   BYTE b = *pbyBlue;
      BYTE gray=(BYTE)(((WORD)r * 59 + (WORD)g * 30 + (WORD)b * 11) / 100);
   *pbyBlue = (BYTE)((m_Blue * gray) / 255); 
   *pbyGreen = (BYTE)((m_Green * gray) / 255);
   *pbyRed = (BYTE)((m_Red * gray) / 255);
  }
}

/***************************************************************/
/*函数名称:NeonLight()                                        */
/*函数类型:void                                               */
/*功能:使图像产生霓虹处理效果。                               */
/***************************************************************/
void MakeColorDib::NeonLight()   //霓虹处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-1;i++) // 每列
  {
    int pby_pt=0;
    //对像素执行算法
    pby_pt=(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-1)*DibWidth+i+3))
       *(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-1)*DibWidth+i+3))
       +(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-2)*DibWidth+i))
       *(*(p_data+(height-j-1)*DibWidth+i)-*(p_data+(height-j-2)*DibWidth+i));
   *(p_temp+(height-j-1)*DibWidth+i)=2*int(sqrt(pby_pt));
   //判断合法性
   if(*(p_temp+(height-j-1)*DibWidth+i)<0)
     *(p_temp+(height-j-1)*DibWidth+i)=0;
   if(*(p_temp+(height-j-1)*DibWidth+i)>255)
     *(p_temp+(height-j-1)*DibWidth+i)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}

/***************************************************************/
/*函数名称:Smoothness()                                       */
/*函数类型:void                                               */
/*功能:使图像平滑处理。                                       */
/***************************************************************/
void MakeColorDib::Smoothness()   //平滑处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    int h[3][3];////定义(3x3)矩阵
 h[0][0] = 1;  h[0][1] = 1; h[0][2] = 1;
 h[1][0] = 1;  h[1][1] = 1; h[1][2] = 1;
 h[2][0] = 1;  h[2][1] = 1; h[2][2] = 1;
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
         double pby_pt=0;
                    //对应的第0行的值乘以矩阵对应值,再相加
       pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
        +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
        +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
                    //对应的第1行的值乘以矩阵对应值,再相加
        +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
        +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
        +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
                    //对应的第2行的值乘以矩阵对应值,再相加
              +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
     +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
     +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(int(pby_pt/9));//取总和的的平均值
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;//删除暂时分配内存
}

/***************************************************************/
/*函数名称:Embossment()                                       */
/*函数类型:void                                               */
/*功能:产生图像浮雕处理效果。                                 */
/***************************************************************/
void MakeColorDib::Embossment()   //浮雕处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height;j++) // 每行
 {
  for(int i=0;i<DibWidth-4;i++) // 每列
  {
    int pby_pt=0;
    //对像素得每个分量执行算法
    pby_pt=*(p_data+(height-j-1)*DibWidth+i)
       -*(p_data+(height-j-1)*DibWidth+i+3)+128;
    *(p_temp+(height-j-1)*DibWidth+i+3)=pby_pt;
   //检验合法性
   if(*(p_temp+(height-j-1)*DibWidth+i+3)<0)
    *(p_temp+(height-j-1)*DibWidth+i+3)=0;
   else if(*(p_temp+(height-j-1)*DibWidth+i+3)>255)
    *(p_temp+(height-j-1)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}

/***************************************************************/
/*函数名称:Spread()                                           */
/*函数类型:void                                               */
/*功能:图像扩散处理。                                         */
/***************************************************************/
void MakeColorDib::Spread()   //扩散处理
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-14;i++) // 每列
  {
    int m=0,n=0;
    m=rand()%5; //取得行随机数
    n=rand()%5; //取得列随机数
    int pby_pt=0;
    pby_pt=*(p_data+(height-j-1-m)*DibWidth+i+3*n);//得到对应随机像素值
    *(p_temp+(height-j-3)*DibWidth+i+6)=pby_pt;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;   //删除暂时分配内存
}

/***************************************************************/
/*函数名称:Sharp()                                            */
/*函数类型:void                                               */
/*功能:图像锐化处理。                                         */
/***************************************************************/
void MakeColorDib::Sharp()   //图像锐化
{
  BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    BYTE *p_temp=new BYTE[height*DibWidth];
 for(int j=0;j<height-1;j++) // 每行
 {
  for(int i=0;i<DibWidth-5;i++) // 每列
  {
         int pby_pt=0;
   pby_pt= *(p_data+(height-j-2)*DibWidth+i+3)
          -*(p_data+(height-j-1)*DibWidth+i);
   *(p_temp+(height-j-2)*DibWidth+i+3)=*(p_data+(height-j-2)*DibWidth+i+3)
                                     +abs(int(pby_pt/4));
   if(*(p_temp+(height-j-2)*DibWidth+i+3)>255)
      *(p_temp+(height-j-2)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:HighLVBO(int m_GaoTong)                            */
/*函数类型:void                                               */
/*参数:int m_GaoTong,用户给定的阈值来选择矩阵                */
/*功能:对图像使用阈值法进行高通滤波。                         */
/***************************************************************/
void MakeColorDib::HighLVBO(int m_GaoTong)   //高通滤波
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[3][3];  ////定义(3x3)矩阵
 if(m_GaoTong==1)
 {   //矩阵1(基本高通)
  h[0][0] =1;   h[0][1] =-2;  h[0][2] =1;
  h[1][0] =-2;  h[1][1] =5;   h[1][2] =-2;
  h[2][0] =1;   h[2][1] =-2;  h[2][2] =1;
 }
 else if(m_GaoTong==2)
 {   //矩阵2(中等高通)
  h[0][0] = 0;   h[0][1] = -1; h[0][2] = 0;
  h[1][0] = -1;  h[1][1] =  5; h[1][2] = -1;
  h[2][0] = 0;   h[2][1] = -1; h[2][2] = 0;
 }
 else
 {   //矩阵3(过量高通)
  h[0][0] = -1;  h[0][1] = -1; h[0][2] = -1;
  h[1][0] = -1;  h[1][1] =  9; h[1][2] = -1;
  h[2][0] = -1;  h[2][1] = -1; h[2][2] = -1;
 }
    BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt=  h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
    //对应的第1行的值乘以矩阵对应值,再相加
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
    +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
    //对应的第2行的值乘以矩阵对应值,再相加
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
    +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
    +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(pby_pt);
   if(pby_pt>255) //判断是否越界
    *(p_temp+(height-j-2)*DibWidth+i+3)=255;
  }
 }
    memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:LowLVBO()                                          */
/*函数类型:void                                               */
/*功能:实现图像低通滤波(3x3)。                                */
/***************************************************************/
void MakeColorDib::LowLVBO()   //低通滤波(3x3)
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
    double h[3][3];////定义(3x3)矩阵
 h[0][0] = 0.1;  h[0][1] = 0.1; h[0][2] = 0.1;
 h[1][0] = 0.1;  h[1][1] = 0.2; h[1][2] = 0.1;
 h[2][0] = 0.1;  h[2][1] = 0.1; h[2][2] = 0.1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   double pby_pt=0;
            //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt=  h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
    //对应的第0行的值乘以矩阵对应值,再相加
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
    +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
    //对应的第0行的值乘以矩阵对应值,再相加
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
    +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
    +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   *(p_temp+(height-j-2)*DibWidth+i+3)=abs(int(pby_pt));
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:LowLVBObig()                                       */
/*函数类型:void                                               */
/*功能:实现图像低通滤波(5x5)。                                */
/***************************************************************/
void MakeColorDib::LowLVBObig()   //低通滤波(5x5)
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[5][5];//定义(5x5)矩阵
 h[0][0] = 1;  h[0][1] = 1; h[0][2] = 1; h[0][3] = 1; h[0][4] = 1;
 h[1][0] = 1;  h[1][1] = 2; h[1][2] = 2; h[1][3] = 2; h[1][4] = 1;
 h[2][0] = 1;  h[2][1] = 2; h[2][2] = 3; h[2][3] = 2; h[2][4] = 1;
 h[3][0] = 1;  h[3][1] = 2; h[3][2] = 2; h[3][3] = 2; h[3][4] = 1;
 h[4][0] = 1;  h[4][1] = 1; h[4][2] = 1; h[4][3] = 1; h[4][4] = 1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j++) // 每行
 {
  for(int i=0;i<DibWidth-14;i++) // 每列
  {
         int pby_pt=0;
         //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt=h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
      +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
      +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
         +h[0][3]*(*(p_data+(height-j-1)*DibWidth+i+9))
      +h[0][4]*(*(p_data+(height-j-1)*DibWidth+i+12))
                  //对应的第1行的值乘以矩阵对应值,再相加
         +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
         +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
      +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
      +h[1][3]*(*(p_data+(height-j-2)*DibWidth+i+9))
      +h[1][4]*(*(p_data+(height-j-2)*DibWidth+i+12))
                  //对应的第2行的值乘以矩阵对应值,再相加
         +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
      +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
      +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6))
      +h[2][3]*(*(p_data+(height-j-3)*DibWidth+i+9))
      +h[2][4]*(*(p_data+(height-j-3)*DibWidth+i+12))
                  //对应的第3行的值乘以矩阵对应值,再相加
         +h[3][0]*(*(p_data+(height-j-4)*DibWidth+i))
         +h[3][1]*(*(p_data+(height-j-4)*DibWidth+i+3))
      +h[3][2]*(*(p_data+(height-j-4)*DibWidth+i+6))
      +h[3][3]*(*(p_data+(height-j-4)*DibWidth+i+9))
      +h[3][4]*(*(p_data+(height-j-4)*DibWidth+i+12))
                  //对应的第4行的值乘以矩阵对应值,再相加
         +h[4][0]*(*(p_data+(height-j-5)*DibWidth+i))
      +h[4][1]*(*(p_data+(height-j-5)*DibWidth+i+3))
      +h[4][2]*(*(p_data+(height-j-5)*DibWidth+i+6))
      +h[4][3]*(*(p_data+(height-j-5)*DibWidth+i+9))
      +h[4][4]*(*(p_data+(height-j-5)*DibWidth+i+12));
                  //为了计算方便我们把除以35(矩阵权和)放在求总和之后
   *(p_temp+(height-j-3)*DibWidth+i+6)=abs(int(pby_pt/35));
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:ShuiPingGROW()                                     */
/*函数类型:void                                               */
/*功能:使图像水平增强。                                       */
/***************************************************************/
void MakeColorDib::ShuiPingGROW()   //水平增强
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[3][1];//定义(3x1)矩阵
 h[0][0] = -1; 
 h[1][0] = 2;
 h[2][0] = -1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的3行的值乘分别以矩阵对应值,再相加
   pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i));
   if(pby_pt>20)
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
   else
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
    delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:ChuiZhiGROW()                                      */
/*函数类型:void                                               */
/*功能:使图像垂直增强。                                       */
/***************************************************************/
void MakeColorDib::ChuiZhiGROW()   //垂直增强
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[1][3];//定义(1x3)矩阵
 h[0][0] = -1;
 h[0][1] = 2;
 h[0][2] = -1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6));
   if(pby_pt>20)
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
   else
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:ShuangXiangGROW()                                  */
/*函数类型:void                                               */
/*功能:使图像双向增强。                                       */
/***************************************************************/
void MakeColorDib::ShuangXiangGROW()    //双向增强
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 int h[3][3];//定义(3x3)矩阵
 h[0][0] = -1;  h[0][1] = -1; h[0][2] = -1;
 h[1][0] = -1;  h[1][1] =  8; h[1][2] = -1;
 h[2][0] = -1;  h[2][1] = -1; h[2][2] = -1;
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-2;j++) // 每行
 {
  for(int i=0;i<DibWidth-8;i++) // 每列
  {
   int pby_pt=0;
   //对应的第0行的值乘以矩阵对应值,再相加
   pby_pt= h[0][0]*(*(p_data+(height-j-1)*DibWidth+i))
    +h[0][1]*(*(p_data+(height-j-1)*DibWidth+i+3))
    +h[0][2]*(*(p_data+(height-j-1)*DibWidth+i+6))
    //对应的第1行的值乘以矩阵对应值,再相加
    +h[1][0]*(*(p_data+(height-j-2)*DibWidth+i))
    +h[1][1]*(*(p_data+(height-j-2)*DibWidth+i+3))
    +h[1][2]*(*(p_data+(height-j-2)*DibWidth+i+6))
    //对应的第2行的值乘以矩阵对应值,再相加
    +h[2][0]*(*(p_data+(height-j-3)*DibWidth+i))
    +h[2][1]*(*(p_data+(height-j-3)*DibWidth+i+3))
    +h[2][2]*(*(p_data+(height-j-3)*DibWidth+i+6));
   if(pby_pt>20)
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt)+100;
   else
    *(p_temp+(height-j-2)*DibWidth+i)=abs(pby_pt);
  }
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}

/***************************************************************/
/*函数名称:Mosaic()                                           */
/*函数类型:void                                               */
/*功能:使图像产生马赛克效果。                                 */
/***************************************************************/
void MakeColorDib::Mosaic()    //马赛克
{
 BYTE *p_data;     //原图数据区指针
 int wide,height,DibWidth;    //原图长、宽、字节宽
 p_data=this->GetData ();   //取得原图的数据区指针
    wide=this->GetWidth ();  //取得原图的数据区宽度
    height=this->GetHeight ();   //取得原图的数据区高度
 DibWidth=this->GetDibWidthBytes();   //取得原图的每行字节数
 BYTE *p_temp=new BYTE[height*DibWidth]; // 暂时分配内存,以保存新图像
 for(int j=0;j<height-4;j+=5) // 每行
 {
     for(int i=0;i<DibWidth-14;i+=15) // 每列
  {   //对应周围(5x5)矩阵蓝色值求和平均
   int pby_pt=0;
   for(int m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {  
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n);
    }
   
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n)=int(pby_pt/25);
    }
            //对应周围(5x5)矩阵绿色值求和平均
   pby_pt=0;
   for(m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n+1);
    }
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n+1)=int(pby_pt/25);
    }
            //对应周围(5x5)矩阵红色值求和平均
   pby_pt=0;
   for(m=0;m<5;m++)
    for(int n=0;n<15;n+=3)
    {
     pby_pt+=*(p_data+(height-j-1-m)*DibWidth+i+n+2);
    }
   for(m=0;m<5;m++)
    for(int n=0;n<14;n+=3)
    {
     *(p_temp+(height-j-1-m)*DibWidth+i+n+2)=int(pby_pt/25);
    }
  }  
 }
 memcpy(p_data,p_temp,height*DibWidth);  // 复制处理后的图像
 delete []p_temp;  //删除暂时分配内存
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/warsour/archive/2009/05/04/4149297.aspx

2018-10-28 23:02:40 Aidam_Bo 阅读数 580
  • Tensorflow-图像处理视频教程

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 课程以图像处理软件Tensorflow作为核心武器,基于图像处理热点话题进行案例实战。选择当下热门模型,使用真实数据集进行实战演示,通俗讲解整个算法模型并使用tensorflow进行实战,详解其中的原理与代码实现。

    1241 人正在学习 去看看 唐宇迪


 

//添加椒盐噪声
void salt(Mat& src,int number)
{
    for (int i = 0; i < number; i++)
    {
        int r = static_cast<int>(rng.uniform(0, src.rows));
        int c = static_cast<int>(rng.uniform(0, src.cols));
        int k = (static_cast<int>(rng.uniform(0, 1000))&1);
        if(k==1)
            src.at<uchar>(r, c) = 255;
        else
            src.at<uchar>(r, c) = 0;
    }
    return;
}
/*
* @ drt :高斯方差
* @ Medium :高斯均值
*/
int Get_Gauss(int Medium, int drt)
{
    //产生高斯样本,以U为均值,D为均方差
    double sum = 0;
    for (int i = 0; i<12; i++) 
        sum += rand() / 32767.00;
    //计算机中rand()函数为-32767~+32767(2^15-1)
    //故sum+为0~1之间的均匀随机变量
    return int(Medium + drt*(sum - 6));
    //产生均值为U,标准差为D的高斯分布的样本,并返回
}
/*
* variance :高斯噪声的方差
*/


 

//添加高斯噪声
void ImgAddGaussNoise1( uchar * dstImgbuff, int srcwith, int srcheigh, int chanels)
{
    assert( srcwith > 0 && srcheigh > 0);
    int bytecount = srcwith * srcheigh * chanels;
 
    for (size_t i = 0; i < bytecount; i++)
    {
        int  iTemp = dstImgbuff[i] + Get_Gauss(0, 20);
        iTemp = iTemp > 255 ? 255 : iTemp;
        iTemp = iTemp < 0 ? 0 : iTemp;
        dstImgbuff[i] = iTemp;
    }
}


 

//均值求取
void Meanvalue(Mat* src, int indexrows, int indexcols, float* meanv, int ker)
{
    int lo = (ker - 1) / 2;
    float total = 0;
    for (int i = indexrows - lo; i <= indexrows + lo; i++)
    {
        for (int j = indexcols - lo; j <= indexcols + lo; j++)
        {
            total += src->at<uchar>(i, j);
        }
    }
    *meanv = total / (ker * ker);
    return;
}
//中值求取
void Media(Mat* src, int indexrows, int indexcols, int* meanv, int ker)
{
    int lo = (ker - 1) / 2;
    vector<int>moreo;
    for (int i = indexrows - lo; i <= indexrows + lo; i++)
    {
        for (int j = indexcols - lo; j <= indexcols + lo; j++)
        {
            moreo.push_back(src->at<uchar>(i, j));
        }
    }
    sort(moreo.begin(), moreo.end());
    *meanv = moreo.at(ker * ker / 2);
    return;
}


 

//局部方差求取
void Vvalue(Mat* src, int indexrows, int indexcols, int* vall, int ker, float mean)
{
    int lo = (ker - 1) / 2;
    float total = 0;
    for (int i = indexrows - lo; i <= indexrows + lo; i++)
    {
        for (int j = indexcols - lo; j <= indexcols + lo; j++)
        {
            total += pow((src->at<uchar>(i, j) - mean), 2);
        }
    }
    *vall = static_cast<int>(total);
    return;
}

 

//像素方差
void Variance(Mat& src, vector<test>& hierachy, int ker)
{
    int row = src.rows;
    int col = src.cols;
    int lo = (ker - 1) / 2;
    for (int ir = lo; ir < row - lo; ir++)
    {
        for (int jc = lo; jc < col - lo; jc++)
        {
            float means;
            int var;
            //计算均值
            Meanvalue(&src, ir, jc, &means, ker);
            Vvalue(&src, ir, jc, &var, ker, means);
            test temp;
            temp.menval = var;
            temp.x = ir;
            temp.y = jc;
            hierachy.push_back(temp);
        }
    }
    return;
}

 

//STL排序方式
bool SortByM1(const test &v1, const test &v2)//注意:本函数的参数的类型一定要与vector中元素的类型一致  
{
    return v1.menval < v2.menval;//升序排列  
}

 

//SSIM 结构相似比
Scalar getMSSIM(const Mat& i1, const Mat& i2)
{
    const double C1 = 6.5025, C2 = 58.5225;
    /***************************** INITS **********************************/
    int d = CV_32F;
 
    Mat I1, I2;
    i1.convertTo(I1, d);           // cannot calculate on one byte large values
    i2.convertTo(I2, d);
 
    int num = I1.channels();
    //cv::imshow("123", I1);
    //cv::waitKey();
 
    Mat I2_2 = I2.mul(I2);        // I2^2
    Mat I1_2 = I1.mul(I1);        // I1^2
    Mat I1_I2 = I1.mul(I2);        // I1 * I2
 
                                   /*************************** END INITS **********************************/
 
    Mat mu1, mu2;   // PRELIMINARY COMPUTING
    GaussianBlur(I1, mu1, Size(11, 11), 1.5);
    GaussianBlur(I2, mu2, Size(11, 11), 1.5);
 
    Mat mu1_2 = mu1.mul(mu1);
    Mat mu2_2 = mu2.mul(mu2);
    Mat mu1_mu2 = mu1.mul(mu2);
 
    Mat sigma1_2, sigma2_2, sigma12;
 
    GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
    sigma1_2 -= mu1_2;
 
    GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
    sigma2_2 -= mu2_2;
 
    GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
    sigma12 -= mu1_mu2;
 
    ///////////////////////////////// FORMULA ////////////////////////////////
    Mat t1, t2, t3;
 
    t1 = 2 * mu1_mu2 + C1;
    t2 = 2 * sigma12 + C2;
    t3 = t1.mul(t2);              // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
 
    t1 = mu1_2 + mu2_2 + C1;
    t2 = sigma1_2 + sigma2_2 + C2;
    t1 = t1.mul(t2);               // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))
 
    Mat ssim_map;
    divide(t3, t1, ssim_map);      // ssim_map =  t3./t1;
 
    Scalar mssim = mean(ssim_map); // mssim = average of ssim map
    return mssim;
}
//功能:局部均值求取 局部方差求取
/* zc 2018/07/08
parameters:
Mat*         src;         //待处理的图像
float*       meanv;       //保存局部均值
float*       dev;         //保存局部方差
int          indexrows;   //要求局部所在行
int          indexcols;   //要求局部所在列
int          ker;         //窗口大小系数
*/
void Meanvalue(Mat* src, float* meanv, float* dev, int indexrows, int indexcols,  int ker)
{
    int lo = (ker - 1) / 2;
    float total = 0;
    float total2 = 0;
    for (int i = indexrows - lo; i <= indexrows + lo; i++)
    {
        for (int j = indexcols - lo; j <= indexcols + lo; j++)
        {
            float temp = static_cast<float>(src->at<uchar>(i, j));
            total += temp;
            total2 += temp*temp;
        }
    }
    int size = ker * ker;
    *meanv = total / size;                                      //均值
    *dev = (total2 - (total*total) / size) / size;              //方差
    return;
}



 
 

2007-07-08 16:39:00 sunny3106 阅读数 2168
  • Tensorflow-图像处理视频教程

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 课程以图像处理软件Tensorflow作为核心武器,基于图像处理热点话题进行案例实战。选择当下热门模型,使用真实数据集进行实战演示,通俗讲解整个算法模型并使用tensorflow进行实战,详解其中的原理与代码实现。

    1241 人正在学习 去看看 唐宇迪

      前些时候做毕业设计,用java做的数字图像处理方面的东西,这方面的资料ms比较少,发点东西上来大家共享一下,主要就是些算法,有自己写的,有人家的,还有改人家的,有的算法写的不好,大家不要见笑。

一 读取bmp图片数据

//  获取待检测图像 ,数据保存在数组 nData[],nB[] ,nG[] ,nR[]中

 public  void getBMPImage(String source) throws Exception {
          
         clearNData();                        //清除数据保存区
         FileInputStream fs = null;
       
        try {
            fs = new FileInputStream(source);
            int bfLen = 14;
            byte bf[] = new byte[bfLen];
            fs.read(bf, 0, bfLen); // 读取14字节BMP文件头
            int biLen = 40;
            byte bi[] = new byte[biLen];
            fs.read(bi, 0, biLen); // 读取40字节BMP信息头

            // 源图宽度
            nWidth = (((int) bi[7] & 0xff) << 24)
                    | (((int) bi[6] & 0xff) << 16)
                    | (((int) bi[5] & 0xff) << 8) | (int) bi[4] & 0xff;

            // 源图高度
            nHeight = (((int) bi[11] & 0xff) << 24)
                    | (((int) bi[10] & 0xff) << 16)
                    | (((int) bi[9] & 0xff) << 8) | (int) bi[8] & 0xff;

            // 位数
            nBitCount = (((int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;

            // 源图大小
            int nSizeImage = (((int) bi[23] & 0xff) << 24)
                    | (((int) bi[22] & 0xff) << 16)
                    | (((int) bi[21] & 0xff) << 8) | (int) bi[20] & 0xff;

            // 对24位BMP进行解析
            if (nBitCount == 24){
                int nPad = (nSizeImage / nHeight) - nWidth * 3;
                nData = new int[nHeight * nWidth];
                nB=new int[nHeight * nWidth];
                nR=new int[nHeight * nWidth];
                nG=new int[nHeight * nWidth];
                byte bRGB[] = new byte[(nWidth + nPad) * 3 * nHeight];
                fs.read(bRGB, 0, (nWidth + nPad) * 3 * nHeight);
                int nIndex = 0;
                for (int j = 0; j < nHeight; j++){
                    for (int i = 0; i < nWidth; i++) {
                        nData[nWidth * (nHeight - j - 1) + i] = (255 & 0xff) << 24
                                | (((int) bRGB[nIndex + 2] & 0xff) << 16)
                                 | (((int) bRGB[nIndex + 1] & 0xff) << 8)
                                | (int) bRGB[nIndex] & 0xff;                     
                        nB[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex]& 0xff;
                        nG[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex+1]& 0xff;
                        nR[nWidth * (nHeight - j - 1) + i]=(int) bRGB[nIndex+2]& 0xff;
                        nIndex += 3;
                    }
                    nIndex += nPad;
                }
 //               Toolkit kit = Toolkit.getDefaultToolkit();
 //               image = kit.createImage(new MemoryImageSource(nWidth, nHeight,
 //                       nData, 0, nWidth));

/*              
//调试数据的读取

                FileWriter fw = new FileWriter("C://Documents and Settings//Administrator//My Documents//nDataRaw.txt");//创建新文件
                PrintWriter out = new PrintWriter(fw);
                for(int j=0;j<nHeight;j++){
                 for(int i=0;i<nWidth;i++){
                  out.print((65536*256+nData[nWidth * (nHeight - j - 1) + i])+"_"
                    +nR[nWidth * (nHeight - j - 1) + i]+"_"
                    +nG[nWidth * (nHeight - j - 1) + i]+"_"
                    +nB[nWidth * (nHeight - j - 1) + i]+" ");
                  
                 }
                 out.println("");
                }
                out.close();
*/         
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }
        finally {
            if (fs != null) {
                fs.close();
            }
        }
     //   return image;
    }

二 由r g b 获取灰度数组

    public  int[] getBrightnessData(int rData[],int gData[],int bData[]){
     
     int brightnessData[]=new int[rData.length];
     if(rData.length!=gData.length || rData.length!=bData.length
       || bData.length!=gData.length){
      return brightnessData;
     }
     else {
      for(int i=0;i<bData.length;i++){
       double temp=0.3*rData[i]+0.59*gData[i]+0.11*bData[i];
       brightnessData[i]=(int)(temp)+((temp-(int)(temp))>0.5?1:0);
      }
      return brightnessData;
     }
     
    }
      
三 直方图均衡化
    public int [] equilibrateGray(int[] PixelsGray,int width,int height)
    {         
         int gray;
         int length=PixelsGray.length;
         int FrequenceGray[]=new int[length];
         int SumGray[]=new int[256];
         int ImageDestination[]=new int[length];
         for(int i = 0; i <length ;i++)
        {
           gray=PixelsGray[i];
              FrequenceGray[gray]++;
        }
          //    灰度均衡化
         SumGray[0]=FrequenceGray[0];
         for(int i=1;i<256;i++){
               SumGray[i]=SumGray[i-1]+FrequenceGray[i]; 
         }
         for(int i=0;i<256;i++) {
               SumGray[i]=(int)(SumGray[i]*255/length); 
         }
         for(int i=0;i<height;i++)
         {
               for(int j=0;j<width;j++)
              {
                  int k=i*width+j;
                  ImageDestination[k]=0xFF000000 | ((SumGray[PixelsGray[k]]<<
                            16 ) | (SumGray[PixelsGray[k]]<< 8 ) | SumGray[PixelsGray[k]]);
               }
          }
         return ImageDestination;
      } 
   
四 laplace2阶滤波,增强边缘,图像锐化
    public int[] laplace2DFileter(int []data,int width,int height){
   
     int filterData[]=new int[data.length];
     int min=10000;
     int max=-10000;
     for(int i=0;i<height;i++){
      for(int j=0;j<width;j++){
       if(i==0 || i==height-1 || j==0 || j==width-1)
               filterData[i*width+j]=data[i*width+j];
       else
        filterData[i*width+j]=9*data[i*width+j]-data[i*width+j-1]-data[i*width+j+1]
                             -data[(i-1)*width+j]-data[(i-1)*width+j-1]-data[(i-1)*width+j+1]
                             -data[(i+1)*width+j]-data[(i+1)*width+j-1]-data[(i+1)*width+j+1];       
       if(filterData[i*width+j]<min)
        min=filterData[i*width+j];
       if(filterData[i*width+j]>max)
        max=filterData[i*width+j];
      }  
     }
//     System.out.println("max: "+max);
//     System.out.println("min: "+min);
     
     for(int i=0;i<width*height;i++){
      filterData[i]=(filterData[i]-min)*255/(max-min);
     }
     return filterData;
    }
        
五 laplace2阶增强滤波,增强边缘,增强系数delt
    public int[] laplaceHigh2DFileter(int []data,int width,int height,double delt){
     
     int filterData[]=new int[data.length];
     int min=10000;
     int max=-10000;
     for(int i=0;i<height;i++){
      for(int j=0;j<width;j++){
       if(i==0 || i==height-1 || j==0 || j==width-1)
               filterData[i*width+j]=(int)((1+delt)*data[i*width+j]);
       else
        filterData[i*width+j]=(int)((9+delt)*data[i*width+j]-data[i*width+j-1])-data[i*width+j+1]
                             -data[(i-1)*width+j]-data[(i-1)*width+j-1]-data[(i-1)*width+j+1]
                             -data[(i+1)*width+j]-data[(i+1)*width+j-1]-data[(i+1)*width+j+1];       
       if(filterData[i*width+j]<min)
        min=filterData[i*width+j];
       if(filterData[i*width+j]>max)
        max=filterData[i*width+j];
      }  
     }
     for(int i=0;i<width*height;i++){
      filterData[i]=(filterData[i]-min)*255/(max-min);
     }
     return filterData;
    }
      
六 局部阈值处理2值化

    //   局部阈值处理2值化,niblack's   method
    /*原理:  
         T(x,y)=m(x,y)   +   k*s(x,y)  
         取一个宽度为w的矩形框,(x,y)为这个框的中心。
         统计框内数据,T(x,y)为阈值,m(x,y)为均值,s(x,y)为均方差,k为参数(推荐-2)计算出t再对(x,y)进行切割255/0。  
         这个算法的优点是     速度快,效果好。  
         缺点是     niblack's   method会产生一定的噪声。 
     */
   
    public int[] localThresholdProcess(int []data,int width,int height,int w,int h,double coefficients,double gate){
     int[] processData=new int[data.length];
     for(int i=0;i<data.length;i++){
      processData[i]=255;
     }
     
     if(data.length!=width*height)
      return processData;
     
     int wNum=width/w;
     int hNum=height/h;
     int delt[]=new int[w*h];
     
     //System.out.println("w; "+w+"  h:"+h+"  wNum:"+wNum+" hNum:"+hNum);
     
     for(int j=0;j<hNum;j++){
      for(int i=0;i<wNum;i++){
     //for(int j=0;j<1;j++){
     // for(int i=0;i<1;i++){ 
        for(int n=0;n<h;n++)
               for(int k=0;k<w;k++){
                delt[n*w+k]=data[(j*h+n)*width+i*w+k];
                //System.out.print("delt["+(n*w+k)+"]: "+delt[n*w+k]+" ");
               }
        //System.out.println();
        /*
        for(int n=0;n<h;n++)
               for(int k=0;k<w;k++){
                System.out.print("data["+((j*h+n)*width+i*w+k)+"]: "+data[(j*h+n)*width+i*w+k]+" ");
               }
        System.out.println();
        */
        delt=thresholdProcess(delt,w,h,coefficients,gate);
        for(int n=0;n<h;n++)
               for(int k=0;k<w;k++){
                processData[(j*h+n)*width+i*w+k]=delt[n*w+k];
               // System.out.print("delt["+(n*w+k)+"]: "+delt[n*w+k]+" ");
               }
        //System.out.println();
        /*
        for(int n=0;n<h;n++)
               for(int k=0;k<w;k++){
                System.out.print("processData["+((j*h+n)*width+i*w+k)+"]: "+processData[(j*h+n)*width+i*w+k]+" ");
               }
        System.out.println();
        */
      }
     }
     
     return processData;
    }
  
七 全局阈值处理2值化
    public int[] thresholdProcess(int []data,int width,int height,double coefficients,double gate){
     int [] processData=new int[data.length];
     if(data.length!=width*height)
      return processData;
     else{
      double sum=0;
      double average=0;
      double variance=0;
      double threshold;
      
      if( gate!=0){
       threshold=gate; 
      }
      else{
            for(int i=0;i<width*height;i++){
            sum+=data[i];
            }
            average=sum/(width*height);
      
            for(int i=0;i<width*height;i++){
              variance+=(data[i]-average)*(data[i]-average);
            }
            variance=Math.sqrt(variance);
            threshold=average-coefficients*variance;
      }
      
         for(int i=0;i<width*height;i++){
          if(data[i]>threshold)
             processData[i]=255;
          else
                processData[i]=0;
         }
      
         return processData;
       }
    }
    
八  垂直边缘检测,sobel算子
    public int[] verticleEdgeCheck(int []data,int width,int height,int sobelCoefficients) throws Exception{
     int filterData[]=new int[data.length];
     int min=10000;
     int max=-10000;
     if(data.length!=width*height)
      return filterData;
     
     try{
     
       for(int i=0;i<height;i++){
       for(int j=0;j<width;j++){
        if(i==0 || i==1 || i==height-1 || i==height-2
           ||j==0 || j==1 || j==width-1 || j==width-2){
               filterData[i*width+j]=data[i*width+j];
         }
         else{
          double average;
            //中心的九个像素点
             //average=data[i*width+j]-Math.sqrt(2)*data[i*width+j-1]+Math.sqrt(2)*data[i*width+j+1]
          average=data[i*width+j]-sobelCoefficients*data[i*width+j-1]+sobelCoefficients*data[i*width+j+1]      
                  -data[(i-1)*width+j-1]+data[(i-1)*width+j+1]
                     -data[(i+1)*width+j-1]+data[(i+1)*width+j+1];
             filterData[i*width+j]=(int)(average);
         }      
        if(filterData[i*width+j]<min)
         min=filterData[i*width+j];
         if(filterData[i*width+j]>max)
         max=filterData[i*width+j];
        }
        }
       for(int i=0;i<width*height;i++){
        filterData[i]=(filterData[i]-min)*255/(max-min);
         }
     
     }
     catch (Exception e)
     {
            e.printStackTrace();
            throw new Exception(e);
        } 
     
     return filterData;
    }
    
       
九  图像平滑:3*3掩模处理(平均处理),降低噪声   
    public int[] filter(int []data,int width,int height) throws Exception{
     
     int filterData[]=new int[data.length];
     int min=10000;
     int max=-10000;
     if(data.length!=width*height)
      return filterData;
     
     try{
     
       for(int i=0;i<height;i++){
       for(int j=0;j<width;j++){
        if(i==0 || i==1 || i==height-1 || i==height-2
           ||j==0 || j==1 || j==width-1 || j==width-2){
               filterData[i*width+j]=data[i*width+j];
         }
         else{
          double average;
            //中心的九个像素点
             average=(data[i*width+j]+data[i*width+j-1]+data[i*width+j+1]
                     +data[(i-1)*width+j]+data[(i-1)*width+j-1]+data[(i-1)*width+j+1]
                     +data[(i+1)*width+j]+data[(i+1)*width+j-1]+data[(i+1)*width+j+1])/9;
             filterData[i*width+j]=(int)(average);
         }      
        if(filterData[i*width+j]<min)
         min=filterData[i*width+j];
         if(filterData[i*width+j]>max)
         max=filterData[i*width+j];
        }
        }
       for(int i=0;i<width*height;i++){
        filterData[i]=(filterData[i]-min)*255/(max-min);
         }
     
     }
     catch (Exception e)
     {
            e.printStackTrace();
            throw new Exception(e);
        } 
     
     return filterData;
    }

 

 

 

 

 

2010-12-28 17:49:00 goustzhu 阅读数 1242
  • Tensorflow-图像处理视频教程

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 课程以图像处理软件Tensorflow作为核心武器,基于图像处理热点话题进行案例实战。选择当下热门模型,使用真实数据集进行实战演示,通俗讲解整个算法模型并使用tensorflow进行实战,详解其中的原理与代码实现。

    1241 人正在学习 去看看 唐宇迪

一 读取bmp图片数据



二 由r g b 获取灰度数组



三 直方图均衡化


四 laplace2阶滤波,增强边缘,图像锐化


五 laplace2阶增强滤波,增强边缘,增强系数delt

六 局部阈值处理2值化



七 全局阈值处理2值化


八 垂直边缘检测,sobel算子



九 图像平滑:3*3掩模处理(平均处理),降低噪声

没有更多推荐了,返回首页