请问用MATLAB识别火焰颜色,用图像像素方差法要怎么弄?

请问用MATLAB识别火焰颜色,用图像像素方差法要怎么弄?,第1张

能识别火焰颜色??光肯定是组合的颜色啊,应该说是rgb的分量把

%%%%%%%%%统计rgb分量

A=imread('C:\Documents and Settings\Dell380\桌面\fabric.png')

r=A(:,:,1)

g=A(:,:,2)

b=A(:,:,3)

subplot(2,2,1)

imshow(A)

title('原图')

A=rgb2gray(A)

bw=im2bw(A)

bw=double(bw)

r=double(r)

g=double(g)

b=double(b)

r1=r.*bw

g1=g.*bw

b1=b.*bw

subplot(2,2,2)

imshow(mat2gray(r1))

title('这个图是用r分量与bw相乘,那么我觉得图中有图肆轮像部分就应该是火焰的红色信息')

subplot(2,2,3)

imshow(mat2gray(g1))

title('同上面说法橘雹闷,应该是绿色的吧')

subplot(2,2,4)

imshow(mat2gray(b1))

title('蓝色信息')

%%%%%%%%rgb分量绘制三维圆弯立体图

A=imread('C:\Documents and Settings\Administrator\桌面\fabric.png')

r=A(:,:,1)

g=A(:,:,2)

b=A(:,:,3)

subplot(2,2,1)

imshow(A)

title('原图')

A=rgb2gray(A)

[m,n]=size(A)

bw=im2bw(A)

bw=imfill(bw,'hole')

subplot(2,2,2)

imshow(bw)

[m,n]=find(bw==1)

c=size(m)

r1=zeros(1,c)

g1=zeros(1,c)

b1=zeros(1,c)

for i=1:c

r1(i)=r(m(i),n(i))

g1(i)=g(m(i),n(i))

b1(i)=b(m(i),n(i))

end

plot3(r1,g1,b1)

class CFireRoutine //烟火程序

{

public:

CFireRoutine()//构造函数

virtual ~CFireRoutine()//虚态的析构函数

// Functs (public)

void InitFire()//初始化

void ClrHotSpots()//清除燃烧点

void InitPallette()//初始化调色板

void SetHotSpots()//设置燃烧点

void MakeLines()//生成扫描线

//渲染(视频内存,宽度,高度)

void Render(DWORD* pVideoMemory,

int iwidth,

int iheight)

//均值(在点x,y处)(像素均值?)

unsigned char Average(int x, int y)

// props

int m_iFlameHeight//火焰高度

int m_iWidth//宽度

int m_iHeight//高度(应该是作图区高度)

//火焰来源,即从点火处的y坐标

int m_iFireSource//The y position for the lit spots

int m_iFireChance//燃烧几率

int m_iAvgFlameWidth//火焰平均宽度

int m_iAlpha//α(深度)

COLORREF m_FireColors[4]//火焰颜色

BYTE* m_pFireBits//火焰数据

DWORD m_pPalletteBuffer[256]//调色板

long* m_pYIndexes//颜色索引

}

//熔浆信亩:

class CPlasmaRoutine

{

public:

CPlasmaRoutine()//构造函数

virtual ~CPlasmaRoutine()//虚态析构函数

// Methods

void SetDefaultValues(VARIANT* pExtParms)//设置缺省参数值(外部变量)

void InitializePlasma(VARIANT* pExtParms)//初始化岩浆参数

void Create(int iWidth,int iHeight)//按视图生成岩浆

void Render(DWORD* pBits, //按照像素位,视图宽度,高度,扫描线渲染

int iwidth,

int iheight,

int iLineLength)

//设置颜色索引的RGB值拆老

void SetRGB(int iIndex,int R,int G,int B)

void InitCostBLTable()//初始化损耗平衡表?BL是不是balance的意思啊?不知道,反正不是对比度和亮度,还是色彩饱和度?好像都不是

void InitPallette()//初始化调色板

void CalcPlasma()//计算岩浆

//按旅坦升照颜色开始,颜色结束,颜色步长创建渐变色,存到buffer里面

void CreateGradient(COLORREF clrStart,COLORREF clrEnd,long lSteps,COLORREF* pBuffer)

// Props

int m_iWidth//视图宽度

int m_iHeight//视图高度

int m_iAlpha//视图深度

BYTE* m_pPlasmaBits//岩浆序列缓冲

DWORD m_pPalletteBuffer[256]//调色板

int m_icostbl[256]//损耗平衡表

COLORREF m_PlasmaColors[16]// Yep 16 colors needed to generate our pallete... 采用16种颜色产生调色板

//以下应该是曲线拟合用的贝塞尔曲线四个控制点和矢量坐标

unsigned char m_a1,m_a2,m_a3,m_a4,m_b1,m_b2,m_b3,m_b4

int m_iModifier1

int m_iModifier2

int m_iModifier3

int m_iModifier4

//双方向修改器(两点拉拽形成的矢量)

int m_iXModifier1

int m_iXModifier2

int m_iYModifier1

int m_iYModifier2

}

// FireRoutine.cpp: implementation of the CFireRoutine class.

//

//////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "FireRoutine.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__

#define new DEBUG_NEW

#endif

//////////////////////////////////////////////////////////////////////

// Construction/Destruction 构造函数,初始化所有参数,注意火源初始值为2,燃烧概率初始值为10

//////////////////////////////////////////////////////////////////////

CFireRoutine::CFireRoutine()

{

m_iWidth = 0

m_iHeight = 0

m_pFireBits = NULL

m_pYIndexes = NULL

m_iFireSource = 2

m_iFireChance = 10

m_iFlameHeight = 50

m_iAlpha = 255

m_FireColors[0] = RGB(0,0,0)// Black

m_FireColors[1] = RGB(255,0,0)// Red

m_FireColors[2] = RGB(255,255,0)// Yellow

m_FireColors[3] = RGB(255,255,255)// White

m_iAvgFlameWidth = 35

}

//析构函数,如果颜色索引和渲染缓冲区存在则注销

CFireRoutine::~CFireRoutine()

{

if(m_pFireBits != NULL)

delete [] m_pFireBits

if(m_pYIndexes != NULL)

delete [] m_pYIndexes

m_pFireBits = NULL

m_pYIndexes = NULL

}

void CFireRoutine::InitFire()

{

// Get Rid of anything already there 初始化火焰,如果存在颜色索引和渲染缓冲则首先注销

if(m_pFireBits != NULL)

delete [] m_pFireBits

if(m_pYIndexes != NULL)

delete [] m_pYIndexes

// Add three to the height 高度自动加三

m_iHeight+=3

m_pYIndexes = new long[m_iHeight]//颜色索引时以火焰高度为长度的一个长整形数组

m_pFireBits = new BYTE[m_iWidth*m_iHeight]//渲染缓冲区为一个W*H长度的字符型数组

// Clear the Fire bits 将火焰缓冲区置零

memset(m_pFireBits,0,(m_iWidth*m_iHeight))

// do all the y index pre-calc.. 在计算之前先将颜色缓冲值初始化为每个元素=宽度*高度

for (int y = m_iHeighty >0y--)

m_pYIndexes[y] = y * m_iWidth

// Create our pallete

InitPallette()//初始化调色板

ClrHotSpots()//清除燃烧点

}

//所谓清除燃烧点就是将渲染缓冲区的某一行清零。哪一行呢?就是颜色索引中火源指向的那一行。

void CFireRoutine::ClrHotSpots()

{

// clear the fire line

memset(&m_pFireBits[m_pYIndexes[m_iFireSource]],0,m_iWidth)

}

//初始化调色板。您可能需要首先了解一下调色板的概念:虽然一个图可能是彩色的,但是每个像素如果

//都按照RGB三个字节方式存储,则成本太高了。调色板在于,假设这个图还是彩图,但是经过色彩分析,

//其中只有256种颜色是图中的常用颜色,这样一个字节就可以代表一个像素了,不过这个字节的值指的

//并不是RGB这种色彩矢量,而是256种颜色的代码,这256种颜色就是这幅图的调色板。

void CFireRoutine::InitPallette()

{

// Create a gradient between all the colors we have for our fire... 为我们的火焰创造一个过渡色使用的所有颜色

long iCount = 0

COLORREF clrStart

COLORREF clrEnd

for(int iColor = 1iColor<4iColor++) //火焰的四个颜色定义

{

clrStart = m_FireColors[iColor-1]//设置过渡色的起始颜色

clrEnd = m_FireColors[iColor]//设置过渡色的终止颜色

int r, g, b // First distance, then starting value 先计算距离,再计算值

float rStep, gStep, bStep // Step size for each color //每种颜色的过渡步进值

// Get the color differences 取得三个颜色RGB的起始颜色和过渡颜色色差

r = (GetRValue(clrEnd) - GetRValue(clrStart))

g = (GetGValue(clrEnd) - GetGValue(clrStart))

b = (GetBValue(clrEnd) - GetBValue(clrStart))

int nSteps = max(abs(r), max(abs(g), abs(b)))//过渡步长数量取为RGB红绿蓝中色差最大者

float fStep = (float)(255/3)/ (float)nSteps//将色差步长值转换为浮点数

// Calculate the step size for each color

rStep = r/(float)nSteps//求得各颜色分量的色差步长值

gStep = g/(float)nSteps

bStep = b/(float)nSteps

// Reset the colors to the starting position 将颜色设置为渐进色初始颜色

r = GetRValue(clrStart)

g = GetGValue(clrStart)

b = GetBValue(clrStart)

for (int iOnBand = 0iOnBand <nStepsiOnBand++) //按照RGB计算出在渐变色全程中每个颜色的实际值

{

//COLORREF color = RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)

COLORREF color = RGB(b + bStep *iOnBand, g + gStep*iOnBand,r+rStep*iOnBand)

long lIndex = (int)(iOnBand * fStep)

if(lIndex+((iColor-1)*85) <255)

m_pPalletteBuffer[lIndex+((iColor-1)*85)] = color//计算结果放到调色板里面去

}

}

// Step on the second color a little bit...向终止颜色过渡,以下颜色生成的内容与上面基本一致。

clrStart = m_FireColors[0]

clrEnd = m_FireColors[1]

for(int kj=0kj<m_iFlameHeightkj++)

m_pPalletteBuffer[kj] = 0

int r, g, b // First distance, then starting value

float rStep, gStep, bStep // Step size for each color

// Get the color differences

r = (GetRValue(clrEnd) - GetRValue(clrStart))

g = (GetGValue(clrEnd) - GetGValue(clrStart))

b = (GetBValue(clrEnd) - GetBValue(clrStart))

int nSteps = max(abs(r), max(abs(g), abs(b)))

float fStep = (float)(85-m_iFlameHeight)/ (float)nSteps

// Calculate the step size for each color

rStep = r/(float)nSteps

gStep = g/(float)nSteps

bStep = b/(float)nSteps

// Reset the colors to the starting position

r = GetRValue(clrStart)

g = GetGValue(clrStart)

b = GetBValue(clrStart)

for (int iOnBand = 0iOnBand <nStepsiOnBand++)

{

//COLORREF color = RGB(r+rStep*iOnBand, g + gStep*iOnBand, b + bStep *iOnBand)

COLORREF color = RGB(b + bStep *iOnBand, g + gStep*iOnBand,r+rStep*iOnBand)

long lIndex = (int)(iOnBand * fStep)

m_pPalletteBuffer[lIndex+(85-m_iFlameHeight)] = color //填写颜色值

}

}

// Macro to get a random integer within a specified range */ 这是一个按照范围取随机数的宏

#define getrandom( min, max ) (( rand() % (int)((( max ) + 1 ) - ( min ))) + ( min ))

#include <time.h>

void CFireRoutine::SetHotSpots() //设置燃烧点

{

ClrHotSpots()//首先清除燃烧点

//m_iAvgFlameWidth

long lPosition = 0//按照横轴位置进行累加,直到抵达宽度界限

while(lPosition <m_iWidth)

{

// see if we should do a flame

if (getrandom(0,100) <m_iFireChance) //得到一个随机数,看看是不是在燃烧概率范围内,如果不是就跳过去

{

// get a flame width

long lFlameWidth = getrandom(1,m_iAvgFlameWidth)//随机取得一个火焰宽度

for(int i=0i<lFlameWidthi++)

{

if(lPosition <m_iWidth) //如果位置在屏幕范围内,设置一个燃烧点

{

m_pFireBits[m_pYIndexes[m_iFireSource]+lPosition] =254// set a hot spot!

lPosition++

}

}

}

lPosition++

}

// for (x = 0x <m_iWidthx++)

// {

// if (getrandom(0,100) <m_iFireChance)

// {

// }

// }

}

void CFireRoutine::MakeLines() //生成渲染扫描线

{

int x, y

for (x = 0x <m_iWidthx++) //横向循环,从屏幕左侧到右侧

{

for (y = m_iFireSourcey<m_iHeight-1y++) //纵向循环,从火源到火焰高度

// for (y = m_iHeighty >m_iFireSourcey--)

{

//m_pFireBits[m_pYIndexes[y-1]+x] =Average(x,y)

m_pFireBits[m_pYIndexes[y+1]+x] =Average(x,y)//火焰值为扫描线均值

}

}

}

unsigned char CFireRoutine::Average(int x, int y)

{

unsigned char ave_color

unsigned char ave1, ave2, ave3, ave4, ave5, ave6, ave7

// Make sure we are not at the last line... 只要不是扫描线最后一样,平均值按照下列方式计算。

if(y == m_iHeight)

ave1 = m_pFireBits[m_pYIndexes[y-1] + x]

else

ave1 = m_pFireBits[m_pYIndexes[y + 1] + x]

//扫描线均值的方法,以x,y为中心,小半径为1,大半径为2的横向椭圆,从这个范围内取得颜色,然后求均值:

//基本上是下面这个图的样式:格式:取点编号(坐标)

/*

1#(x, y+1)

6#(x-2, y) 4#(x-1, y) 7#(x,y) 3#(x+1, y) 5#(x+2, y)

2#(x, y-1)

*/

ave2 = m_pFireBits[m_pYIndexes[y - 1] + x]

ave3 = m_pFireBits[m_pYIndexes[y] + x + 1]

ave4 = m_pFireBits[m_pYIndexes[y] + x - 1]

ave5 = m_pFireBits[m_pYIndexes[y] + x + 2]

ave6 = m_pFireBits[m_pYIndexes[y] + x - 2]

ave7 = m_pFireBits[m_pYIndexes[y] + x]

ave_color = (ave1 + ave2 + ave3 + ave4 + ave5 + ave6 + ave7) / 7

//求出颜色均值并返回

return(ave_color)

}

//按照视频内存进行渲染

void CFireRoutine::Render(DWORD* pVideoMemory,

int iwidth,

int iheight

)

{

SetHotSpots() // generate random hotspots 产生燃烧点

MakeLines() // do all the math and screen updating //产生扫描线,更新屏幕

// Right now Im just going to blit it right onto the video memory //向视频内存做BitBlt缓冲拷贝

unsigned char* pSrcBitlin// = m_pFireBits+(m_iWidth*3)// get rid of our fire source //获取火源

BYTE *dst//=(BYTE*)Dib->pVideoMemory

BYTE r

BYTE g

BYTE b

for(int i=0i<m_iHeight-3i++) //逐行扫描

{

dst = (BYTE*)&pVideoMemory[(iwidth*i)]//取得视频当前行

pSrcBitlin =&m_pFireBits[m_pYIndexes[i+3]]//设置扫描线数据指针

for(int x=0x<m_iWidthx++)

{

//合成颜色,注意,是索引颜色取RGB分量后加上深度和饱和度,移位

r = GetRValue(m_pPalletteBuffer[pSrcBitlin[x]])

g = GetGValue(m_pPalletteBuffer[pSrcBitlin[x]])

b = GetBValue(m_pPalletteBuffer[pSrcBitlin[x]])

dst[0]=(BYTE)(((r-dst[0])*m_iAlpha+(dst[0]<<8))>>8)

dst[1]=(BYTE)(((g-dst[1])*m_iAlpha+(dst[1]<<8))>>8)

dst[2]=(BYTE)(((b-dst[2])*m_iAlpha+(dst[2]<<8))>>8)

dst+=4

}

}

}

关于岩浆和水波的源代码,概念差不多,都是首先建立颜色模型、然后匹配到缓冲中去,仔细对比一下就看懂了

火焰的颜色是由(1)一定要看是什么样的可燃物质(2)要达到着火点(3)空气对流好(4)氧气是否充足(5)燃烧时温度的高低(6)吸收什么光,放出什么光(7)还要看具体的需求是什么,共七条。举例如下:燃气灶烧的是石油液化气如果是白光则说明了进入的空气过量,要调节阀门小一些至出蓝色,因为过量空气带走了大量热量,人们是要利用它的热,来煮饭,神纳禅而不是利用它的光照明,使火焰不能反射光,光线全通过。当发蓝光时,就是氧气量适当,石油液化气充分燃烧,又温度很高,煮饭炒菜易熟,日光中的蓝色被反射出来。又如比较乙烯和乙炔的燃烧更清楚了,乙烯中含碳量没有乙炔多燃烧时反射蓝光。而乙炔燃烧时,赤热游离的碳原子过多光线全通过而发白光,赤热的碳上升出现黑色浓烟。这属化学上研究乙烯、乙炔含有碳量多少的对比实验。再看点煤油灯,不用灯马口,又不用灯的玻璃照时出现黄红光,当用上马口和玻璃照时,调节灯芯高度就会发白光,煤油中的碳氢化合物全部燃烧。这是用来照明,故要求白光。因为日光是七色光(红、橙、黄、绿、青、蓝、紫)的混合为白色。冷空气从马口下方进入从灯照的上方升出,空气对流好,煤油充分燃烧,所以发白光。再讲一个例子,工业上用氢气在氯气中燃烧来制氯化氢气体时是发出苍白色火焰,这才是燃料气充分燃烧的表现。<不给河南人丢脸>同志收到来函,再补充一点。火焰的颜色是由于电子在核外运动时有不同的能级,各种能级上的能量是一个一个不连续的确定值,在正式常状态下,原子总是处在能量最低的基态,当原子被火焰、电弧、电火花所激发时,核外电子就会吸收能量而被激发跃迁到较高的能级上去,处于激发态的电子不稳定,当它跃回到能量较低的能级时就会放发出具有一定能量、一定波长的光谱线。三种光谱线(焰色、电弧、电火花)强度不同但对同茄郑一原子仍是同一谱线。各种元素的特殊焰色就是可见光区的光谱线的颜色。常见可见光是各种不同颜色的混合光即白光。各种颜色的光都对应有一定的波长。,又由于各元素的原子或离子的结构的不同,所放出的光的波长就会不一样,呈现的颜色也就各不相同了!在研究可见光的范畴内,当电子由高能级跃回到较低的能级时,会向外发射出不同的波长的光,再对照太阳光中的七色光的波长,是哪个波段光的颜色,我们看到就是哪种光.它是不受外界环境的影响的,不论外界是白天还是晚上.例如夜幕放烟花,我们见到五彩滨汾的光,就是这个道理.我们在研究问题时是用太阳的白光,通过三棱镜产生的七色光的波长,反过来研究物质,在上面三种情况下产生的光的.就知道那种原子或离子在(焰色、电弧、电火花)三种光谱中的波长了!当然还有不可见光,那不是此题讨论的范畴了!只因水平有限,只好拙度一下,对不起了!

下面看一下对照表

暗红色:600摄氏度左右。

深红色:700摄氏度左右。

橘红色:1000摄氏度左右。

纯橘色:1100摄氏度左右。

金橘色:1200摄氏度左右。

金黄色:1300摄氏度左右。

金白色:1400摄氏度左右。

纯白色:1500摄游尘氏度左右。

白蓝色:1500摄氏度以上。

天蓝色:一般冶炼达不到此程度。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12500933.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存