直方图匹配,又称直方图规定化,即变换原图的直方图为规定的某种形式的直方图,从而使两幅图像具有类似的色调和反差。直方图匹配属于非线性点运算。

直方图规定化的原理:对两个直方图都做均衡化,变成相同的归一化的均匀直方图,以此均匀直方图为媒介,再对参考图像做均衡化的逆运算

     /// <summary>
/// 直方图匹配
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="matchingBmp">匹配图像</param>
/// <param name="dstBmp">处理后图像</param>
/// <returns>处理成功 true 失败 false</returns>
public static bool HistogramMatching(Bitmap srcBmp, Bitmap matchingBmp, out Bitmap dstBmp)
{
if (srcBmp == null || matchingBmp == null)
{
dstBmp = null;
return false;
}
dstBmp = new Bitmap(srcBmp);
Bitmap tempSrcBmp = new Bitmap(srcBmp);
Bitmap tempMatchingBmp = new Bitmap(matchingBmp);
double[] srcCpR = null;
double[] srcCpG = null;
double[] srcCpB = null;
double[] matchCpB = null;
double[] matchCpG = null;
double[] matchCpR = null;
//分别计算两幅图像的累计概率分布
getCumulativeProbabilityRGB(tempSrcBmp, out srcCpR, out srcCpG, out srcCpB);
getCumulativeProbabilityRGB(tempMatchingBmp, out matchCpR, out matchCpG, out matchCpB); double diffAR = , diffBR = , diffAG = , diffBG = , diffAB = , diffBB = ;
byte kR = , kG = , kB = ;
//逆映射函数
byte[] mapPixelR = new byte[];
byte[] mapPixelG = new byte[];
byte[] mapPixelB = new byte[];
//分别计算RGB三个分量的逆映射函数
//R
for (int i = ; i < ; i++)
{
diffBR = ;
for (int j = kR; j < ; j++)
{
//找到两个累计分布函数中最相似的位置
diffAR = Math.Abs(srcCpR[i] - matchCpR[j]);
if (diffAR - diffBR < 1.0E-08)
{//当两概率之差小于0.000000001时可近似认为相等
diffBR = diffAR;
//记录下此时的灰度级
kR = (byte)j;
}
else
{
kR = (byte)Math.Abs(j - );
break;
}
}
if (kR == )
{
for (int l = i; l < ; l++)
{
mapPixelR[l] = kR;
}
break;
}
mapPixelR[i] = kR;
}
//G
for (int i = ; i < ; i++)
{
diffBG = ;
for (int j = kG; j < ; j++)
{
diffAG = Math.Abs(srcCpG[i] - matchCpG[j]);
if (diffAG - diffBG < 1.0E-08)
{
diffBG = diffAG;
kG = (byte)j;
}
else
{
kG = (byte)Math.Abs(j - );
break;
}
}
if (kG == )
{
for (int l = i; l < ; l++)
{
mapPixelG[l] = kG;
}
break;
}
mapPixelG[i] = kG;
}
//B
for (int i = ; i < ; i++)
{
diffBB = ;
for (int j = kB; j < ; j++)
{
diffAB = Math.Abs(srcCpB[i] - matchCpB[j]);
if (diffAB - diffBB < 1.0E-08)
{
diffBB = diffAB;
kB = (byte)j;
}
else
{
kB = (byte)Math.Abs(j - );
break;
}
}
if (kB == )
{
for (int l = i; l < ; l++)
{
mapPixelB[l] = kB;
}
break;
}
mapPixelB[i] = kB;
}
//映射变换
BitmapData bmpData = dstBmp.LockBits(new Rectangle(, , dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
unsafe
{
byte* ptr = null;
for (int i = ; i < dstBmp.Height; i++)
{
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = ; j < dstBmp.Width; j++)
{
ptr[j * + ] = mapPixelR[ptr[j * + ]];
ptr[j * + ] = mapPixelG[ptr[j * + ]];
ptr[j * ] = mapPixelB[ptr[j * ]];
}
}
}
dstBmp.UnlockBits(bmpData);
return true;
} /// <summary>
/// 计算各个图像分量的累计概率分布
/// </summary>
/// <param name="srcBmp">原始图像</param>
/// <param name="cpR">R分量累计概率分布</param>
/// <param name="cpG">G分量累计概率分布</param>
/// <param name="cpB">B分量累计概率分布</param>
private static void getCumulativeProbabilityRGB(Bitmap srcBmp, out double[] cpR, out double[] cpG, out double[] cpB)
{
if (srcBmp == null)
{
cpB = cpG = cpR = null;
return;
}
cpR = new double[];
cpG = new double[];
cpB = new double[];
int[] hR = null;
int[] hG = null;
int[] hB = null;
double[] tempR = new double[];
double[] tempG = new double[];
double[] tempB = new double[];
getHistogramRGB(srcBmp, out hR, out hG, out hB);
int totalPxl = srcBmp.Width * srcBmp.Height;
for (int i = ; i < ; i++)
{
if (i != )
{
tempR[i] = tempR[i - ] + hR[i];
tempG[i] = tempG[i - ] + hG[i];
tempB[i] = tempB[i - ] + hB[i];
}
else
{
tempR[] = hR[];
tempG[] = hG[];
tempB[] = hB[];
}
cpR[i] = (tempR[i] / totalPxl);
cpG[i] = (tempG[i] / totalPxl);
cpB[i] = (tempB[i] / totalPxl);
}
} /// <summary>
/// 获取图像三个分量的直方图数据
/// </summary>
/// <param name="srcBmp">图像</param>
/// <param name="hR">R分量直方图数据</param>
/// <param name="hG">G分量直方图数据</param>
/// <param name="hB">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[];
hB = new int[];
hG = new int[];
BitmapData bmpData = srcBmp.LockBits(new Rectangle(, , srcBmp.Width, srcBmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
unsafe
{
byte* ptr = null;
for (int i = ; i < srcBmp.Height; i++)
{
ptr = (byte*)bmpData.Scan0 + i * bmpData.Stride;
for (int j = ; j < srcBmp.Width; j++)
{
hB[ptr[j * ]]++;
hG[ptr[j * + ]]++;
hR[ptr[j * + ]]++;
}
}
}
srcBmp.UnlockBits(bmpData);
return;
}

c#数字图像处理(七)直方图匹配的更多相关文章

  1. OpenCV-跟我一起学数字图像处理之直方图均衡化

    从这篇博文开始,小生正式从一个毫不相干专业转投数字图像处理.废话不多说了,talk is cheap. show me the code. 直方图均衡化目的 由于一些图像灰度的分布过于集中,这样会导致 ...

  2. Win8 Metro(C#)数字图像处理--3.3图像直方图计算

    原文:Win8 Metro(C#)数字图像处理--3.3图像直方图计算 /// <summary> /// Get the array of histrgram. /// </sum ...

  3. Win8Metro(C#)数字图像处理--2.34直方图规定化

    原文:Win8Metro(C#)数字图像处理--2.34直方图规定化  [函数名称] WriteableBitmap HistogramSpecificateProcess(WriteableBi ...

  4. Win8Metro(C#)数字图像处理--2.30直方图均衡化

    原文:Win8Metro(C#)数字图像处理--2.30直方图均衡化 [函数名称] 直方图均衡化函数HistogramEqualProcess(WriteableBitmap src) [算法说明] ...

  5. FPGA与数字图像处理技术

    数字图像处理方法的重要性源于两个主要应用领域: 改善图像信息以便解释. 为存储.传输和表示而对图像数据进行处理,以便于机器自动理解. 图像处理(image processing): 用计算机对图像进行 ...

  6. 数字图像处理:基于MATLAB的车牌识别项目 标签: 图像处理matlab算法 2017-06-24 09:17 98人阅读 评论(0)

    学过了数字图像处理,就进行一个综合性强的小项目来巩固一下知识吧.前阵子编写调试了一套基于MATLAB的车牌识别的项目的代码.今天又重新改进了一下代码,识别的效果好一点了,也精简了一些代码.这里没有使用 ...

  7. FPGA经典:Verilog传奇与基于FPGA的数字图像处理原理及应用

    一 简述 最近恶补基础知识,借了<<Verilog传奇>>,<基于FPGA的嵌入式图像处理系统设计>和<<基千FPGA的数字图像处理原理及应用>& ...

  8. 数字图像处理的Matlab实现(4)—灰度变换与空间滤波

    第3章 灰度变换与空间滤波(2) 3.3 直方图处理与函数绘图 基于从图像亮度直方图中提取的信息的亮度变换函数,在诸如增强.压缩.分割.描述等方面的图像处理中扮演着基础性的角色.本节的重点在于获取.绘 ...

  9. 数字图像处理实验(总计23个)汇总 标签: 图像处理MATLAB 2017-05-31 10:30 175人阅读 评论(0)

    以下这些实验中的代码全部是我自己编写调试通过的,到此,最后进行一下汇总. 数字图像处理实验(1):PROJECT 02-01, Image Printing Program Based on Half ...

随机推荐

  1. javascript拷贝

    function copy(obj){ //浅拷贝 var result = {}; for(var attr in obj){ result[attr] = obj[attr]; } return ...

  2. 很多.net 程序员不知道又非常重要的 .net高级调试技巧.调试别人的dll方法内的变量

    事情是这样的, 最近需要开发Orcale的数据库. 于是使用了EF 加上 Oracle.ManagedDataAccess.Client 这个Oracle.ManagedDataAccess 很好用, ...

  3. 复盘:错误理解zuul路径匹配,无法使用zuul

    场景: 项目中用到zuul时,配置url总是有问题,无法路由到对应微服务. 配置如下: zuul: routes: m2-member: path: /member/* serviceId: m2-m ...

  4. Maven工程

    maven:父子工程 1,父工程并没有实质性的内容,所有的jar包都在里面,也就是说只需要管理jar包即可,不参与任务方法逻辑 2,在父工程中拥有很多的子模块,每一个子模块都代表了不用的包如(pack ...

  5. CentOS 7 端口白名单设置

    # 查看白名单列表 firewall-cmd --zone=public --list-ports # 添加白名单端口 firewall-cmd --zone=public --add-port=/t ...

  6. TCP/IP||ARP/RARP

    1.ARP ARP(地址解析协议)主要为IP地址到对应的硬件提供动态映射,过程是自动完成 在网络接口有一个硬件地址(48 bit),在硬件层次上的数据帧交换必须有正确的接口地址,但是32 bit 的I ...

  7. k8s集群———flannel网络

    #master执行将内网通信地址写入etcd中,确保flannel能与etcd通信 #添加 /opt/etcd/bin/etcdctl --ca-file=/opt/etcd/ssl/ca.pem - ...

  8. [quack] A browser extension to Clean website pages ADs

    1. youdao.com result page Before: After: Later we will add more and more. Or you can submit issues t ...

  9. docker-覆盖网络

    docker network rm docker_gwbridge Error response from daemon: Error response from daemon: network ne ...

  10. 2019年最值得关注的AI领域技术突破及未来展望

    选自venturebeat 翻译:魔王.一鸣 前言 AI 领域最杰出的头脑如何总结 2019 年技术进展,又如何预测 2020 年发展趋势呢?本文介绍了 Soumith Chintala.Celest ...