图像处理之直方图匹配.
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
直方图匹配,又称直方图规定化,即变换原图的直方图为规定的某种形式的直方图,从而使两幅图像具有类似的色调和反差。直方图匹配属于非线性点运算。
直方图规定化的原理:对两个直方图都做均衡化,变成相同的归一化的均匀直方图,以此均匀直方图为媒介,再对参考图像做均衡化的逆运算
/// <summary>
///直方图匹配
//R
for (int i = 0; i < 256; i++) {
diffBR = 1;
for (int j = kR; j < 256; j++) {
//找到两个累计分布函数中最相似的位置
diffAR = Math.Abs(srcCpR[i] - matchCpR[j]);
if (diffAR - diffBR < 1.0E-08) {//当两概率之差小于0.000000001时可近似认为相等
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="cpR">R分量累计概率分布</param>
/// <param name="cpG">G分量累计概率分布</param>
/// <param name="cpB">B分量累计概率分布</param>
public static void getHistogramRGB(Bitmap srcBmp, out int[] hR, out int[] hG, out int[] hB) {
if (srcBmp == null) {
hR = hB = hG = null;
return;
}
hR = new int[256];
return;
}
cpR = new double[256];
cpG = new double[256];
cpB = new double[256];
int[] hR = null;
int[] hG = null;
int[] hB = null;
double[] tempR = new double[256];
ptr[j * 3 + 1] = mapPixelG[ptr[j * 3 + 1]];
ptr[j * 3] = mapPixelB[ptr[j * 3]];
}
}
}
dstBmp.UnlockBits(bmpData);
return true;
}
/// <summary>
///计算各个图像分量的累计概率分布
diffBG = diffAG;
kG = (byte)j;
}
else {
kG = (byte)Math.Abs(j - 1);
break;
}
}
if (kG == 255) {
for (int l = i; l < 256; l++) {
mapPixelG[l] = kG;
}
break;
}
mapPixelG[i] = kG;
return false;
}
dstBmp = new Bitmap(srcBmp);
Bitmap tempSrcBmp = new Bitmap(srcBmp);
Bitmap tempMatchingBmp = new Bitmap(matchingBmp);
double[] srcCpR = null;
private static void getCumulativeProbabilityRGB(Bitmap srcBmp, out double[] cpR, out double[] cpG, out double[] cpB) {
if (srcBmp == null) {
cpB = cpG = cpR = null;
}
//B
for (int i = 0; i < 256; i++) {
diffBB = 1;
for (int j = kB; j < 256; j++) {
diffAB = Math.Abs(srcCpB[i] - matchCpB[j]);
if (diffAB - diffBB < 1.0E-08) {
}
//映射变换
BitmapData bmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe {
tempG[0] = hG[0];
tempB[0] = hB[0];
}
cpR[i] = (tempR[i] / totalPxl);
cpG[i] = (tempG[i] / totalPxl);
cpB[i] = (tempB[i] / totalPxl);
}
}
/// <summary>
///获取图像三个分量的直方图数据
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="matchingBmp">匹配图像</param>
/// <param name="dstBmp">处理后图像</param>
/// <returns>处理成功true失败false</returns>
diffBR = diffAR;
//记录下此时的灰度级
kR = (byte)j;
}
else {
kR = (byte)Math.Abs(j - 1);
break;
}
}
if (kR == 255) {
for (int l = i; l < 256; l++) {
mapPixelR[l] = kR;
}
break;
double[] srcCpG = null;
double[] srcCpB = null;
double[] matchCpB = null;
double[] matchCpG = null;
double[] matchCpR = null;
//分别计算两幅图像的累计概率分布
getCumulativeProbabilityRGB(tempSrcBmp, out srcCpR, out srcCpG, out srcCpB);
unsafe {
byte* ptr = null;
for (int i = 0; i < srcBmp.Height; i++) {
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < srcBmp.Width; j++) {
/// </summary>
/// <param name="srcBmp">图像</param>
/// <param name="hR">R分量直方图数据</param>
/// <param name="hG">G分量直方图数据</param>
/// <param name="hB">B分量直方图数据</param>
hB = new int[256];
hG = new int[256];
BitmapData bmpData = srcBmp.LockBits(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
diffBB = diffAB;
kB = (byte)j;
}
else {
kB = (byte)Math.Abs(j - 1);
break;
}
}
if (kB == 255) {
for (int l = i; l < 256; l++) {
mapPixelB[l] = kB;
}
break;
}
mapPixelB[i] = kB;
byte kR = 0, kG = 0, kB = 0;
//逆映射函数
byte[] mapPixelR = new byte[256];
byte[] mapPixelG = new byte[256];
byte[] mapPixelB = new byte[256];
//分别计算RGB三个分量的逆映射函数
double[] tempG = new double[256];
double[] tempB = new double[256];
getHistogramRGB(srcBmp, out hR, out hG, out hB);
int totalPxl = srcBmp.Width * srcBmp.Height;
for (int i = 0; i < 256; i++) {
if (i != 0) {
tempR[i] = tempR[i - 1] + hR[i];
tempG[i] = tempG[i - 1] + hG[i];
tempB[i] = tempB[i - 1] + hB[i];
}
else {
tempR[0] = hR[0];
byte* ptr = null;
for (int i = 0; i < dstBmp.Height; i++) {
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < dstBmp.Width; j++) {
ptr[j * 3 + 2] = mapPixelR[ptr[j * 3 + 2]];
public static bool HistogramMatching(Bitmap srcBmp, Bitmap matchingBmp, out Bitmap dstBmp) {
if (srcBmp == null || matchingBmp == null) {
dstBmp = null;
getCumulativeProbabilityRGB(tempMatchingBmp, out matchCpR, out matchCpG, out matchCpB);
double diffAR = 0, diffBR = 0, diffAG = 0, diffBG = 0, diffAB = 0, diffBB = 0;
hB[ptr[j * 3]]++;
hG[ptr[j * 3 + 1]]++;
hR[ptr[j * 3 + 2]]++;
}
}
}
srcBmp.UnlockBits(Hale Waihona Puke BaidumpData);
return;
}
}
mapPixelR[i] = kR;
}
//G
for (int i = 0; i < 256; i++) {
diffBG = 1;
for (int j = kG; j < 256; j++) {
diffAG = Math.Abs(srcCpG[i] - matchCpG[j]);
if (diffAG - diffBG < 1.0E-08) {
直方图规定化的原理:对两个直方图都做均衡化,变成相同的归一化的均匀直方图,以此均匀直方图为媒介,再对参考图像做均衡化的逆运算
/// <summary>
///直方图匹配
//R
for (int i = 0; i < 256; i++) {
diffBR = 1;
for (int j = kR; j < 256; j++) {
//找到两个累计分布函数中最相似的位置
diffAR = Math.Abs(srcCpR[i] - matchCpR[j]);
if (diffAR - diffBR < 1.0E-08) {//当两概率之差小于0.000000001时可近似认为相等
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="cpR">R分量累计概率分布</param>
/// <param name="cpG">G分量累计概率分布</param>
/// <param name="cpB">B分量累计概率分布</param>
public static void getHistogramRGB(Bitmap srcBmp, out int[] hR, out int[] hG, out int[] hB) {
if (srcBmp == null) {
hR = hB = hG = null;
return;
}
hR = new int[256];
return;
}
cpR = new double[256];
cpG = new double[256];
cpB = new double[256];
int[] hR = null;
int[] hG = null;
int[] hB = null;
double[] tempR = new double[256];
ptr[j * 3 + 1] = mapPixelG[ptr[j * 3 + 1]];
ptr[j * 3] = mapPixelB[ptr[j * 3]];
}
}
}
dstBmp.UnlockBits(bmpData);
return true;
}
/// <summary>
///计算各个图像分量的累计概率分布
diffBG = diffAG;
kG = (byte)j;
}
else {
kG = (byte)Math.Abs(j - 1);
break;
}
}
if (kG == 255) {
for (int l = i; l < 256; l++) {
mapPixelG[l] = kG;
}
break;
}
mapPixelG[i] = kG;
return false;
}
dstBmp = new Bitmap(srcBmp);
Bitmap tempSrcBmp = new Bitmap(srcBmp);
Bitmap tempMatchingBmp = new Bitmap(matchingBmp);
double[] srcCpR = null;
private static void getCumulativeProbabilityRGB(Bitmap srcBmp, out double[] cpR, out double[] cpG, out double[] cpB) {
if (srcBmp == null) {
cpB = cpG = cpR = null;
}
//B
for (int i = 0; i < 256; i++) {
diffBB = 1;
for (int j = kB; j < 256; j++) {
diffAB = Math.Abs(srcCpB[i] - matchCpB[j]);
if (diffAB - diffBB < 1.0E-08) {
}
//映射变换
BitmapData bmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe {
tempG[0] = hG[0];
tempB[0] = hB[0];
}
cpR[i] = (tempR[i] / totalPxl);
cpG[i] = (tempG[i] / totalPxl);
cpB[i] = (tempB[i] / totalPxl);
}
}
/// <summary>
///获取图像三个分量的直方图数据
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="matchingBmp">匹配图像</param>
/// <param name="dstBmp">处理后图像</param>
/// <returns>处理成功true失败false</returns>
diffBR = diffAR;
//记录下此时的灰度级
kR = (byte)j;
}
else {
kR = (byte)Math.Abs(j - 1);
break;
}
}
if (kR == 255) {
for (int l = i; l < 256; l++) {
mapPixelR[l] = kR;
}
break;
double[] srcCpG = null;
double[] srcCpB = null;
double[] matchCpB = null;
double[] matchCpG = null;
double[] matchCpR = null;
//分别计算两幅图像的累计概率分布
getCumulativeProbabilityRGB(tempSrcBmp, out srcCpR, out srcCpG, out srcCpB);
unsafe {
byte* ptr = null;
for (int i = 0; i < srcBmp.Height; i++) {
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < srcBmp.Width; j++) {
/// </summary>
/// <param name="srcBmp">图像</param>
/// <param name="hR">R分量直方图数据</param>
/// <param name="hG">G分量直方图数据</param>
/// <param name="hB">B分量直方图数据</param>
hB = new int[256];
hG = new int[256];
BitmapData bmpData = srcBmp.LockBits(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
diffBB = diffAB;
kB = (byte)j;
}
else {
kB = (byte)Math.Abs(j - 1);
break;
}
}
if (kB == 255) {
for (int l = i; l < 256; l++) {
mapPixelB[l] = kB;
}
break;
}
mapPixelB[i] = kB;
byte kR = 0, kG = 0, kB = 0;
//逆映射函数
byte[] mapPixelR = new byte[256];
byte[] mapPixelG = new byte[256];
byte[] mapPixelB = new byte[256];
//分别计算RGB三个分量的逆映射函数
double[] tempG = new double[256];
double[] tempB = new double[256];
getHistogramRGB(srcBmp, out hR, out hG, out hB);
int totalPxl = srcBmp.Width * srcBmp.Height;
for (int i = 0; i < 256; i++) {
if (i != 0) {
tempR[i] = tempR[i - 1] + hR[i];
tempG[i] = tempG[i - 1] + hG[i];
tempB[i] = tempB[i - 1] + hB[i];
}
else {
tempR[0] = hR[0];
byte* ptr = null;
for (int i = 0; i < dstBmp.Height; i++) {
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = 0; j < dstBmp.Width; j++) {
ptr[j * 3 + 2] = mapPixelR[ptr[j * 3 + 2]];
public static bool HistogramMatching(Bitmap srcBmp, Bitmap matchingBmp, out Bitmap dstBmp) {
if (srcBmp == null || matchingBmp == null) {
dstBmp = null;
getCumulativeProbabilityRGB(tempMatchingBmp, out matchCpR, out matchCpG, out matchCpB);
double diffAR = 0, diffBR = 0, diffAG = 0, diffBG = 0, diffAB = 0, diffBB = 0;
hB[ptr[j * 3]]++;
hG[ptr[j * 3 + 1]]++;
hR[ptr[j * 3 + 2]]++;
}
}
}
srcBmp.UnlockBits(Hale Waihona Puke BaidumpData);
return;
}
}
mapPixelR[i] = kR;
}
//G
for (int i = 0; i < 256; i++) {
diffBG = 1;
for (int j = kG; j < 256; j++) {
diffAG = Math.Abs(srcCpG[i] - matchCpG[j]);
if (diffAG - diffBG < 1.0E-08) {