人体骨骼核扫描图的混合空间增强
数字图像处理混合空间增强法学习
报告
软件系统测试报告下载sgs报告如何下载关于路面塌陷情况报告535n,sgs报告怎么下载竣工报告下载
学生姓名: 邹晓敏 学 号: 6103313025 专业班级: 数媒131 一、 学习目的与内容:
对混合模糊图像进行处理,为得到一个满意的结果,对其应用多种互补的图像增强技术,最终得到良好效果。本次的数字图像处理实验是对人体骨骼核扫描图片进行混合增强处理,通过混合增强突出骨骼的更多细节。原图中骨骼比较模糊,边缘不够清晰,对比度不够,对此应该采取的策略是首先用拉普拉斯变换突出图像中的小细节,然后用梯度法突出其边缘。平滑后的拉普拉斯变换将用于掩蔽拉普拉斯图像,最后用灰度变换来扩展图像的灰度动态范围。
二、 算法介绍:
软件开发环境:
基于vc++ MFC实现软件编写。
具体步骤:
(1)拉普拉斯算子
拉普拉斯算子是最简单的各向同性微分算子,具有旋转不变性。一个二维图像函数 的拉普拉斯变换是各向同性的二阶导数,定义为:
为了更适合于数字图像处理,将该方程表示为离散形式
另外,拉普拉斯算子还可以表示成模板的形式,一般增强技术对于陡峭的边缘和缓慢变化的边缘很难确定其边缘线的位置。但此算子却可用二次微分正峰和负峰之间的过零点来确定,对孤立点或端点更为敏感,因此特别适用于以突出图像中的孤立点、孤立线或线端点为目的的场合。
用以上算子与原图进行卷积,得到中心像素点与邻域像素点的差值。得到的拉普拉斯变换图M1,M1与原图相加得到M2,锐化原图。
(2)边缘检测
一幅图像的边缘是通过一阶和二阶数字导数来检测得到的。边缘的宽度取决于从初始灰度级跃变到最终灰度级的斜坡的长度。这个长度又取决于斜度,而斜度又取决于模糊程度。所以,我们可知,模糊的边缘使其变粗,而清晰的边缘使其变得较细。
(,)xy一幅数字图像的一阶导数是基于各种二维梯度的近似值。图像在位置的梯fxy(,)度定义为下列向量:
,f,,,, Gx,,,x,,,,,f,,,fGy,,,,,,,y,,
(,)xy梯度向量指向在坐标的的最大变化率方向。在边缘检测中,一个重要的f
,f量是向量的大小,用表示,。一般来讲称为梯度。考虑到图片中的噪声,所以在此处,f
用sobel算子。Sobel卷积因子为:
该算子包含两组3x3的矩阵,分别为横向及纵向,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。如果以A代表原始图像,Gx及Gy分别代表经横向及纵向边缘检测的图像灰度值,其公式如下:
sobel算子运算结果得到M3,保留边缘去除噪声
根据最后运行的结果显示,sobel图像的边缘要比拉普拉斯图像的边缘突出很多。拉普拉斯变换作为一种二阶微分算子,在图像细节的增强处理方面有明显的优点,但拉普拉斯变换与梯度变换相比较会产生更多的噪声。其中位于平滑区域的噪声非常显眼,梯度变换在灰度变换的区域的相应要比拉普拉斯更强烈,而梯度变换对噪声和小细节的响应要比拉普拉斯变换弱,而且可以通过均值滤波器对其进行平滑处理而进一步的降低,对梯度图像进行平滑处理并用拉普拉斯图像与他相乘。处理后的结果在灰度变化强的区域仍然保留细节,而在灰
2
度变化相对平坦的区域则减少噪声,这种处理可以看做是将拉普拉斯变换与梯度变换的有点
结合。
(3)平滑处理
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围8个像素,构成一个滤波模板,即去掉目标
像素本身),再用模板中的全体像素的平均值来代替原来像素值。
一个5*5的均值滤波器对图像进行平滑处理,5*5的均值滤波器对图像进行平滑处理得
到图像M4。再由M2和M4相乘形成掩蔽图像M5。
(4)锐化图像
拉普拉斯与平滑后的梯度图像乘积的结果可以看出,强边缘的优势和可见噪声的减
少。将乘积图像与原始图像相加就得到了锐化图像。与原始图像相比,锐化处理后的图像细节增加很明显。单独使用拉普拉斯或者梯度变换不能达到这种效果。而且以上的锐化过程没有影响图像的灰度动态变化范围。进行增强处理的最后一步就是扩大锐化图像的灰度动态范围。将M5和原图M求和锐化得到M6,再对M6做幂律变换,扩散灰度范围,提升对比度,但幂次必须小于1。得到最后的混合空间加强图像M7。
三、 源程序核心代码及运行结果
//拉普拉斯(Laplacian)算子
void CImageProcessingDoc::LaplaceOperator(CImage * pSrcImage, CImage * pDstImage,
int laplacetype,bool bCalibration)
{ int x;int y;int i;int j;
int mWidth = pSrcImage->GetWidth();
int mHeight = pSrcImage->GetHeight();
int mRowBytes = pSrcImage->GetPitch();
BYTE *rImageData = (BYTE *)pDstImage->GetBits();
int *pBitData = NULL;
pBitData = new int[3 * mHeight*mWidth];
BYTE * pData = NULL;
pData = new BYTE[9];
int Laplace0[3][3] = { { 0,1,0},{1,-4,1 }, { 0,1,0 } };
int Laplace1[3][3] = { { 1,1,1},{1,-8, 1}, { 1,1,1 } };
int Laplace2[3][3] = { {0,-1,0},{-1,4,-1}, { 0,-1,0} };
int Laplace3[3][3] = { {-1,-1,-1},{-1,8,-1},{-1,-1,-1} };
3
int *p;
switch (laplacetype)
{
case 1: p = (int *)Laplace0;
break;
case 2: p = (int *)Laplace1;
break;
case 3: p = (int *)Laplace2;
break;
case 4: p = (int *)Laplace3;
break;
default:
return;
}
int laplace;
for (y = 0; y < mHeight; y++)
for (x = 0; x < mWidth; x++)
{
CopyAreaBlueFromImgBits(pSrcImage, pData, x, y, 1, 1);
laplace = 0;
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
{
laplace += pData[j * 3 + i] * p[j*3 + i];
}
pBitData[3 * y * mWidth + x * 3] = laplace;
CopyAreaGreenFromImgBits(pSrcImage, pData, x, y, 1, 1);
laplace = 0;
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
{
laplace += pData[j * 3 + i] * p[j*3 + i];
}
pBitData[3 * y * mWidth + x * 3 + 1] = laplace;
CopyAreaRedFromImgBits(pSrcImage, pData, x, y, 1, 1);
laplace = 0;
4
for (j = 0; j < 3; j++)
for (i = 0; i < 3; i++)
{
laplace += pData[j * 3 + i] * p[j*3 + i];
}
pBitData[3 * y * mWidth + x * 3 + 2] = laplace;
}
int minBlue = pBitData[0];
int minGreen = pBitData[1];
int minRed = pBitData[2];
for (y = 0; y < mHeight; y++)
for (x = 0; x < mWidth; x++)
{
if (pBitData[3 * y * mWidth + x * 3] < minBlue)
minBlue = pBitData[3 * y * mWidth + x * 3];
if (pBitData[3 * y * mWidth + x * 3 + 1] < minGreen)
minGreen = pBitData[3 * y * mWidth + x * 3 + 1];
if (pBitData[3 * y * mWidth + x * 3 + 2] < minRed)
minRed = pBitData[3 * y * mWidth + x * 3 + 2];
}
for (y = 0; y < mHeight; y++)
for (x = 0; x < mWidth; x++)
{
laplace = pBitData[3 * y * mWidth + x * 3];
laplace = bCalibration ?(laplace + minBlue>255?255: laplace + minBlue):
((laplace > 255) ? 255 : (laplace < 0 ? 0 : laplace));
rImageData[y*mRowBytes + x * 3] = laplace;
laplace = pBitData[3 * y * mWidth + x * 3 + 1];
laplace = bCalibration ? (laplace + minBlue>255 ? 255 : laplace + minBlue) :
((laplace > 255) ? 255 : (laplace < 0 ? 0 : laplace));
rImageData[y*mRowBytes + x * 3 + 1] = laplace;
laplace = pBitData[3 * y * mWidth + x * 3 + 2];
laplace = bCalibration ? (laplace + minBlue>255 ? 255 : laplace + minBlue) :
((laplace > 255) ? 255 : (laplace < 0 ? 0 : laplace));
rImageData[y*mRowBytes + x * 3 + 2] = laplace;
}
if (pData)
delete[] pData;
5
pData = NULL;
if (pBitData)
delete pBitData;
pBitData = NULL;
}
//Sobel算子
void CImageProcessingDoc::SobelOperator(CImage * pSrcImage, CImage * pDstImage) {
int x;
int y;
int dx;
int dy;
int sobel;
int mWidth = pSrcImage->GetWidth();
int mHeight = pSrcImage->GetHeight();
int mRowBytes = pSrcImage->GetPitch();
BYTE *sImageData = (BYTE *)pSrcImage->GetBits();
BYTE *rImageData = (BYTE *)pDstImage->GetBits();
for (y = 1; y < mHeight - 1; y++)
for (x = 1; x < mWidth - 1; x++)
{
dx = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 0] - sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 0]
+ 2 * (sImageData[(y - 1)*mRowBytes + x * 3 + 0] - sImageData[(y + 1)*mRowBytes + x * 3 + 0])
+ sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 0] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 0];
dy = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 0] - sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 0]
+ 2 * (sImageData[y*mRowBytes + (x - 1) * 3 + 0] - sImageData[y*mRowBytes + (x - 1) * 3 + 0])
+ sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 0] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 0];
sobel = (int)(sqrt(dx*dx*1.0 + dy*dy));
sobel = (sobel > 255) ? 255 : sobel;
rImageData[y*mRowBytes + x * 3 + 0] = sobel;
dx = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 1] - sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 1]
+ 2 * (sImageData[(y - 1)*mRowBytes + x * 3 + 1] - sImageData[(y +
6
1)*mRowBytes + x * 3 + 1])
+ sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 1] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 1];
dy = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 1] - sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 1]
+ 2 * (sImageData[y*mRowBytes + (x - 1) * 3 + 1] - sImageData[y*mRowBytes + (x - 1) * 3 + 1])
+ sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 1] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 1];
sobel = (int)(sqrt(dx*dx*1.0 + dy*dy));
sobel = (sobel > 255) ? 255 : sobel;
rImageData[y*mRowBytes + x * 3 + 1] = sobel;
dx = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 2] - sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 2]
+ 2 * (sImageData[(y - 1)*mRowBytes + x * 3 + 2] - sImageData[(y + 1)*mRowBytes + x * 3 + 2])
+ sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 2] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 2];
dy = sImageData[(y - 1)*mRowBytes + (x - 1) * 3 + 2] - sImageData[(y - 1)*mRowBytes + (x + 1) * 3 + 2]
+ 2 * (sImageData[y*mRowBytes + (x - 1) * 3 + 2] - sImageData[y*mRowBytes + (x - 1) * 3 + 2])
+ sImageData[(y + 1)*mRowBytes + (x - 1) * 3 + 2] - sImageData[(y + 1)*mRowBytes + (x + 1) * 3 + 2];
sobel = (int)(sqrt(dx*dx*1.0 + dy*dy));
sobel = (sobel > 255) ? 255 : sobel;
rImageData[y*mRowBytes + x * 3 + 2] = sobel;
}
}
//均值滤波
void CImageProcessingDoc::MeanOperator(CImage * pSrcImage, CImage * pDstImage, int m,
int n)
{
int x;
int y;
int mWidth = pSrcImage->GetWidth();
int mHeight = pSrcImage->GetHeight();
int mRowBytes = pSrcImage->GetPitch();
BYTE *rImageData = (BYTE *)pDstImage->GetBits();
7
double sumB;
double sumG;
double sumR;
int nums = (2 * m + 1)*(2 * n + 1);
BYTE * pData = NULL;
pData = new BYTE[3 * nums];
int lineBytes = 3 * (2 * n + 1);
for (y = 0; y < mHeight; y++)
for (x = 0; x < mWidth; x++)
{
CopyAreaRGBFromImgBits(pSrcImage, pData, x, y, m, n);
sumB = sumG = sumR = 0;
for (int j = -m; j <= m; j++)
for (int i = -n; i <= n; i++)
{
sumB += pData[(j + m)*lineBytes + (i + n) * 3 + 0];
sumG += pData[(j + m)*lineBytes + (i + n) * 3 + 1];
sumR += pData[(j + m)*lineBytes + (i + n) * 3 + 2];
}
rImageData[y*mRowBytes + x * 3] = (int)(sumB/nums);
rImageData[y*mRowBytes + x * 3 + 1] = (int)(sumG / nums);
rImageData[y*mRowBytes + x * 3 + 2] = (int)(sumR / nums);
}
if (pData)
delete[] pData;
pData = NULL;
}
//幂律变换
void CImageProcessingDoc::OnPowerTransform() {
// TODO: 在此添加命令处理程序代码
if (m_sImage.IsNull())
{
AfxMessageBox(_T("请打开要处理的图像~"));
return;
}
CDialogPowerParameters mdlg;
if (mdlg.DoModal() == IDCANCEL)
8
return;
int x;
int y;
int nRows = m_sImage.GetHeight();
int nCols = m_sImage.GetWidth();
int nBPP = m_sImage.GetBPP();
BYTE nRed, nGreen, nBlue;
double dGrey;
m_rImage.Destroy();
if (!m_rImage.Create(nCols, nRows, nBPP))
return;
BYTE *sImageData = (BYTE *)m_sImage.GetBits();
BYTE *rImageData = (BYTE *)m_rImage.GetBits();
int nRowBytes = m_sImage.GetPitch();
for (y = 0; y < nRows; y++)
for (x = 0; x < nCols; x++)
{
nBlue = sImageData[y * nRowBytes + x * 3 + 0];
nGreen = sImageData[y * nRowBytes + x * 3 + 1];
nRed = sImageData[y * nRowBytes + x * 3 + 2];
dGrey = 0.299*nRed + 0.587*nGreen + 0.114*nBlue;
dGrey = 255 * mdlg.m_power_c * exp(mdlg.m_power_gama * log(dGrey / 255 +
0.00001));
rImageData[y * nRowBytes + x * 3] = (BYTE)dGrey;
rImageData[y * nRowBytes + x * 3 + 1] = (BYTE)dGrey;
rImageData[y * nRowBytes + x * 3 + 2] = (BYTE)dGrey;
}
UpdateAllViews(NULL);
}
//图像相加
void CImageProcessingDoc::OnImageAdd()
{
CImage lsImage;
CString strFilter;
9
CSimpleArray
aguidFileTypes;
HRESULT hResult;
// 获取CImage支持的图像文件的过滤字符串
hResult = m_sImage.GetExporterFilterString(strFilter, aguidFileTypes, _T("All Image
Files"));
if (FAILED(hResult))
{
AfxMessageBox(_T("GetExporterFilter函数失败!"));
return;
}
CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
if (IDOK != dlg.DoModal())
return;
lsImage.Destroy();
// 将外部图像文件装载到CImage对象中
hResult = lsImage.Load(dlg.GetPathName());
if( ( lsImage.GetHeight() != m_sImage.GetHeight() ) || ( lsImage.GetWidth() !=
m_sImage.GetWidth() ) )
{
lsImage.Destroy();
AfxMessageBox(_T("本软件只处理相同大小图像的逻辑与代数运算~"));
return;
}
CDialogImageAddRatio mdlg;
if (mdlg.DoModal() != IDOK)
{
lsImage.Destroy();
return;
}
double lambuda = mdlg.addRatio / 100.0;
int x; int y;
int nRows = m_sImage.GetHeight();
int nCols = m_sImage.GetWidth();
int nBPP = m_sImage.GetBPP();
m_rImage.Destroy();
if (!m_rImage.Create(nCols, nRows, nBPP))
{
lsImage.Destroy();
return;
}
BYTE *sImageData = (BYTE *)m_sImage.GetBits();
10
BYTE *lsImageData = (BYTE *)lsImage.GetBits();
BYTE *rImageData = (BYTE *)m_rImage.GetBits();
int nRowBytes = m_sImage.GetPitch();
int sRowBytes = m_sImage.GetPitch();
for (y = 0; y < nRows; y++)
for (x = 0; x < nCols ; x++)
{
rImageData[y * nRowBytes + x * 3 + 0] = (int)(lambuda * sImageData[y * nRowBytes + x * 3 + 0] + (1- lambuda) * lsImageData[y * nRowBytes + x * 3 + 0] );
rImageData[y * nRowBytes + x * 3 + 1] = (int)(lambuda * sImageData[y * nRowBytes + x * 3 + 1] + (1 - lambuda) * lsImageData[y * nRowBytes + x * 3 + 1]);
rImageData[y * nRowBytes + x * 3 + 2] = (int)(lambuda * sImageData[y * nRowBytes + x * 3 + 2] + (1 - lambuda) * lsImageData[y * nRowBytes + x * 3 + 2]);
}
lsImage.Destroy();
UpdateAllViews(NULL);
}
//图像相乘
void CImageProcessingDoc::OnImageMul()
{
CImage lsImage;
CString strFilter;
CSimpleArray aguidFileTypes;
HRESULT hResult;
// 获取CImage支持的图像文件的过滤字符串
hResult = m_sImage.GetExporterFilterString(strFilter, aguidFileTypes, _T("All Image Files"));
if (FAILED(hResult))
{
AfxMessageBox(_T("GetExporterFilter函数失败!"));
return;
}
CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
if (IDOK != dlg.DoModal())
return;
lsImage.Destroy();
// 将外部图像文件装载到CImage对象中
hResult = lsImage.Load(dlg.GetPathName());
11
int x;
int y;
int nRows = m_sImage.GetHeight();
int nCols = m_sImage.GetWidth();
int nBPP = m_sImage.GetBPP();
m_rImage.Destroy();
if (!m_rImage.Create(nCols, nRows, nBPP))
{
lsImage.Destroy();
return;
}
BYTE *sImageData = (BYTE *)m_sImage.GetBits();
BYTE *lsImageData = (BYTE *)lsImage.GetBits();
BYTE *rImageData = (BYTE *)m_rImage.GetBits();
int nRowBytes = m_sImage.GetPitch();
int sRowBytes = m_sImage.GetPitch();
int nrgb;
for (y = 0; y < nRows; y++)
for (x = 0; x < nCols; x++)
{
nrgb = (int)(sImageData[y * nRowBytes + x * 3 + 0] * lsImageData[y * nRowBytes + x
* 3 + 0]);
nrgb = (nrgb < 0) ? 0 : ((nrgb>255) ? 255 : nrgb);
rImageData[y * nRowBytes + x * 3 + 0] = nrgb;
nrgb = (int)(sImageData[y * nRowBytes + x * 3 + 1] * lsImageData[y * nRowBytes +
x * 3 + 1]);
nrgb = (nrgb < 0) ? 0 : ((nrgb>255) ? 255 : nrgb);
rImageData[y * nRowBytes + x * 3 + 1] = nrgb;
nrgb = (int)(sImageData[y * nRowBytes + x * 3 + 2] * lsImageData[y * nRowBytes + x
* 3 + 2]);
nrgb = (nrgb < 0) ? 0 : ((nrgb>255) ? 255 : nrgb);
rImageData[y * nRowBytes + x * 3 + 2] = nrgb;
}
lsImage.Destroy();
UpdateAllViews(NULL);
}
12
各个处理过程后得到的图片M-M7:
四、 实验
总结
初级经济法重点总结下载党员个人总结TXt高中句型全总结.doc高中句型全总结.doc理论力学知识点总结pdf
本次实验所用的图像是一幅人体骨骼核扫描图像,常用于检查人体疾病,我们的目的是通过图像锐化突出骨骼的更多细节来增强图像。由于图像灰度的动态范围很窄并且有很高的噪声内容,所以很难对其增强。本实验采用的策略是,首先用拉普拉斯法突出图像的小细节,然后用梯度法突出其边缘。平滑过的梯度图像将用于掩蔽拉普拉斯图像,最后使用灰度变换来增大图像的灰度动态范围。把多种方法结合起来达到用一种方法无法实现的效果的混合空间增强法可以得到一幅具有较高视觉细节内容的图像。
本次实验我使用了课本提供的算法流程,熟悉运用了拉普拉斯锐化和幂次变换提升对比度的原理方法。但是其中还是有一些比较难理解的内容,通过查询资料一步一步了解清楚。了解了数字图像处理中的简单使用,不仅加深了对书本知识的理解,也加深了对于本门课程的了解和喜爱。
13