📄 hsi.cpp
字号:
/**$6
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
#include "stdafx.h"
#include "HSI.h"
#include <math.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define DEGREES_PER_RADIAN (180.0 / 3.14159265358979)
//#define pi 3.1415926
// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
// 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
// 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
// biWidth'
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
// define UNDEFINED_HUE -1.000
#define UNDEFINED_HUE 0.000
#define ZERO_SATURATION 0.0
/**
=======================================================================================================================
*
=======================================================================================================================
*/
int RgbToLuv(RGB *RgbPtr, LUV *LuvPtr)
{
double r, g, b;
double x,y,z;
double up,vp,x0,y0,z0,u0,v0;
double a;
a=1.0/3.0;
x0=97.28;y0=100;z0=116.14;
r = (double) RgbPtr->r;
g = (double) RgbPtr->g;
b = (double) RgbPtr->b;
x=0.607*r+0.174*g+0.20*b;
y=0.299*r+0.587*g+0.114*b;
z=0.066*g+1.116*b;
up=4*x/(x+15*y+3*z);
vp=9*y/(x+15*y+3*z);
u0=4*x0/(x0+15*y0+3*z0);
v0=9*y0/(x0+15*y0+3*z0);
if(y/y0>0.08856)
LuvPtr->l=116*pow(double(y/y0),a)-16;
else
LuvPtr->l=903.3*y/y0;
LuvPtr->u=13*(LuvPtr->l)*(up-u0);
LuvPtr->v=13*(LuvPtr->l)*(vp-v0);
return 0;
}
int RgbToHsi(RGB *RgbPtr, HSI *HsiPtr)
{
double R, G, B, Sum, Quotient;
double Radians, Angle, MinValue, MaxValue, TempDouble1, TempDouble2;
R = ((double) RgbPtr->r) / 255.0;
G = ((double) RgbPtr->g) / 255.0;
B = ((double) RgbPtr->b) / 255.0;
Sum = R + G + B;
HsiPtr->Intensity = Sum / 3.0;
MinValue = (R < G) ? R : G;
MinValue = (B < MinValue) ? B : MinValue;
MaxValue = (R > G) ? R : G;
MaxValue = (B > MaxValue) ? B : MaxValue;
if(HsiPtr->Intensity < 0.0001)
HsiPtr->Saturation = ZERO_SATURATION;
else
HsiPtr->Saturation = 1.0 - (3.0 * MinValue) / Sum;
if(MinValue == MaxValue)
{
HsiPtr->Hue = UNDEFINED_HUE;
HsiPtr->Saturation = ZERO_SATURATION;
return 0;
}
TempDouble1 = (((R - G) + (R - B)) / 2.0);
TempDouble2 = (R - G) * (R - G) + (R - B) * (G - B);
Quotient = (TempDouble1 / sqrt(TempDouble2));
if(Quotient > 0.99999999999999999)//0.99999999999999999
Radians = 0.0;
else if(Quotient < -0.99999999999999999)//0.99999999999999999
Radians = 3.1415926535;
else
Radians = acos(TempDouble1 / sqrt(TempDouble2));
Angle = Radians * DEGREES_PER_RADIAN;
if(B > G)
HsiPtr->Hue = 360.0 - Angle;
else
HsiPtr->Hue = Angle;
return 0;
}
/*************************************************************************
*
* 函数名称:
* HoughDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数,必须是4的倍数)
* LONG lHeight - 源图像高度(象素数)
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用于对检测图像中的平行直线。如果图像中有两条平行的直线,则将这两条平行直线
* 提取出来。
*
* 要求目标图像为只有0和255两个灰度值的灰度图像。
************************************************************************/
/*
BOOL WINAPI HoughDIB(LPBYTE lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像的指针
LPBYTE lpSrc;
// 图像每行的字节数
LONG lLineBytes;
//指向变换域的指针
int* lpTransArea;
HLOCAL hTransArea;
//变换域的尺寸
int iMaxDist;
int iMaxAngleNumber;
//变换域的坐标
int iDist;
int iAngleNumber;
//循环变量
long i;
long j;
//像素值
unsigned char pixel;
//存储变换域中的两个最大值
MaxValue MaxValue1;
MaxValue MaxValue2;
double sintab[180],costab[180];
for(int x=-90;x<90;x++)
{
sintab[x+90]=sin(x*pi/180);
costab[x+90]=cos(x*pi/180);
}
//计算变换域的尺寸
//最大距离
iMaxDist = (int) (sqrt(lWidth*lWidth + lHeight*lHeight)+1);
//角度从-180-180,每格1度
iMaxAngleNumber = 180;
//为变换域分配内存
hTransArea = LocalAlloc(LHND, iMaxAngleNumber *iMaxDist * sizeof(int));
// 锁定内存
lpTransArea = (int * )LocalLock(hTransArea);
// 初始化新分配的内存,设定初始值为0
//lpTrans = (int *)lpTransArea;
memset(lpTransArea, 0, iMaxAngleNumber *iMaxDist * sizeof(int));
// 计算图像每行的字节数
lLineBytes =lWidth * 3;
//lLineBytes = WIDTHBYTES(lWidth * 24);
for(j =50;j<lHeight-50;j++)
{
for(i =20;i<lWidth-20;i++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + 3*i;
//取得当前指针处的像素值,注意要转换为unsigned char型
pixel = (unsigned char)*lpSrc;
//目标图像中含有0和255外的其它灰度值
if(pixel != 255 && *lpSrc != 0)
return FALSE;
//如果是黑点,则在变换域的对应各点上加1
if(pixel == 255 )
{
//注意步长是2度
for(iAngleNumber=0; iAngleNumber<180; iAngleNumber++)
{
iDist = (int)(i*costab[iAngleNumber] + \
j*sintab[iAngleNumber]);
if(iDist<0)continue;
//变换域的对应点上加1
*(lpTransArea+iDist*180+iAngleNumber) = \
*(lpTransArea+iDist*180+iAngleNumber) +1;
}
}
}
}
//找到变换域中的两个最大值点
MaxValue1.Value=0;
MaxValue2.Value=0;
/*
MaxValue1.Dist=100;
MaxValue2.Dist=100;
MaxValue1.AngleNumber=45;
MaxValue2.AngleNumber=45;
//找到第一个最大值点
for (iDist=0; iDist<iMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumber<180; iAngleNumber++)
{
if(*(lpTransArea+iDist*180+iAngleNumber)>MaxValue1.Value)
{
MaxValue1.Value = *(lpTransArea+iDist*180+iAngleNumber);
MaxValue1.Dist = iDist;
MaxValue1.AngleNumber = iAngleNumber;
}
}
}
//将第一个最大值点附近清零
for (iDist = -19;iDist < 20;iDist++)
{
for(iAngleNumber=-5; iAngleNumber<6; iAngleNumber++)
{
if(iDist+MaxValue1.Dist>=0 && iDist+MaxValue1.Dist<iMaxDist \
&& iAngleNumber+MaxValue1.AngleNumber>=0 && iAngleNumber+MaxValue1.AngleNumber<=iMaxAngleNumber)
{
*(lpTransArea+(iDist+MaxValue1.Dist)*iMaxAngleNumber+\
(iAngleNumber+MaxValue1.AngleNumber))=0;
}
}
}
//找到第二个最大值点
for (iDist=0; iDist<iMaxDist;iDist++)
{
for(iAngleNumber=0; iAngleNumber<180; iAngleNumber++)
{
if((int)*(lpTransArea+iDist*180+iAngleNumber)>MaxValue2.Value)
{
MaxValue2.Value = (int)*(lpTransArea+iDist*180+iAngleNumber);
MaxValue2.Dist = iDist;
MaxValue2.AngleNumber = iAngleNumber;
}
}
}
//判断两直线是否平行
// if(abs(MaxValue1.AngleNumber-MaxValue2.AngleNumber)<=42)
// {
//两直线平行,在缓存图像中重绘这两条直线
for(j = 0; j <lHeight; j++)
{
for(i = 0;i <lWidth; i++)
{
// 指向缓存图像倒数第j行,第i个象素的指针
lpSrc = (unsigned char *)lpDIBBits + lLineBytes * j + 3*i;
//如果该点在某一条平行直线上,则在缓存图像上将该点赋为黑MaxValue1.AngleNumber
//在第一条直线上
iDist = (int) ((i*costab[MaxValue1.AngleNumber]+\
j*sintab[MaxValue1.AngleNumber]));
if(iDist<0)continue;
if (iDist == MaxValue1.Dist )
{
*lpSrc = (unsigned char)0;
*(lpSrc+1) = (unsigned char)0xff;
*(lpSrc+2) = (unsigned char)0;
}
//在第二条直线上
iDist = (int) (i*costab[MaxValue2.AngleNumber]+\
j*sintab[MaxValue2.AngleNumber]);
if(iDist<0)continue;
if (iDist == MaxValue2.Dist)
{
*lpSrc = (unsigned char)0;
*(lpSrc+1) = (unsigned char)0;
*(lpSrc+2) = (unsigned char)0xff;
}
}
}
//}
// 复制腐蚀后的图像
// memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
// LocalUnlock(hNewDIBBits);
// LocalFree(hNewDIBBits);
// 释放内存
LocalUnlock(hTransArea);
LocalFree(hTransArea);
// 返回
return TRUE;
}
*/
void TableSmooth(int *pg,int m,int n)
{
int i,j,k;
for(j=0;j<n;j++)
{
k=pg[0];//保存第一点数据
for(i=1;i<m-1;i++)
pg[i-1]=(pg[i-1]+pg[i]+pg[i+1])/3;
for(i=m-1;i>0;i--)
pg[i]=pg[i-1];
pg[0]=k;//恢复第一点数据
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -