OpenCV2编程手册笔记之 4.3查找表修改图像外观
来源:互联网 发布:c 遍历二维数组 编辑:程序博客网 时间:2024/06/05 09:32
在一张灰度图像的直方图中,显示了图像灰度分配的范围和强度,我们利用这个信息,就可以做到修改,甚至提高某一个图像的质量。
实现方法:
使用查找表,查找表是一个简单的一对一(一对多)函数,在这个查找表中定义了如何将原始的像素转换成新的像素
现在,我们先来看看如何利用查找表修改图像的外观,在这里我们把一张灰度图变成他的负片
继续我们在4.2中的工作,在Histogram1D类中加入applyLookUp这个方法(不想回去看的,我在下面粘所有代码)
先来介绍一下LUT这个查找表应用函数:
LUT(InputArray src, InputArray lut, OutputArray dst);
函数十分简单,第一个参数是你要修改的图像,第二个参数是查找表,第三个参数是输出图像。注意,查找表是数组的形式
我们首先定义一个查找表lut,在opencv中,我们选择用cv::Mat的形式定义数组
int dim = 256; cv::Mat lut(1, &dim, CV_8U);
在opencv的Mat类定义中,我们可以找到: Mat(int ndims, const int* sizes, int type);
这就是这个定义的依据。定义好了查找表后,我们就可以直接调用applyLookUp这个方法了
cv::Mat Histogram1D::applyLookUp(const cv::Mat &image, const cv::Mat &lookup) { cv::Mat result; cv::LUT(image, lookup, result); return result; }
---------------------一条分割线-----------------------
在了解如何利用查找表修改图像之后,我们现在利用查找表来提高图像的对比度
这一部分中,我们通过拉伸直方图,来获取提高对比度的图像。我们使用的公式是
255.0*(i-imin)/(imax-imin)+0.5
我们在这里定义一个方法stretch,用来提高对比度
cv::Mat Histogram1D::stretch(const cv::Mat &image, int minValue)
其中,minValue是用户自定义的最小值划分点
这个最小值划分点的含义是:当某一个灰度值中所含有的元素个数小于这个阈值时,我们就把这个灰度值忽略掉。
比如说,你将minValue设为100,那就是说,从直方图左侧开始查找,假设0灰度值中含有50个元素,1灰度值中含有60个元素,2中含有150个元素,那么imin值就记为2,退出左侧查找;同时,从直方图的右侧查找,假设255含有20个元素,254含有80个元素,253含有120个元素,那么imax就记为253。我们把imin和imax称为图像的最左端和最右端。
在这之后,我们还是创建一个查找表lut并填充他
cv::Mat lut(1, &dim, CV_8U); for (int i = 0; i<256; i++) { if (i < imin) lut.at<uchar>(i) = 0; else if (i > imax) lut.at<uchar>(i) = 255; else lut.at<uchar>(i) = static_cast<uchar>(255.0*(i - imin) / (imax - imin) + 0.5); }这样,我们就把最左端左侧的部分都定义为0,最右端的部分都定义为255。也就是说,我们把上文举例中的0,1都定义为0;255,254都定义为255;其他容器中按照公式。
最后,上代码。
//Histogram1D类#pragma once#include "stdafx.h"#include <opencv2\opencv.hpp>class Histogram1D{private:int histSize[1];float hranges[2];const float * ranges[1];int channels[1];public:Histogram1D(){histSize[0] = 256;hranges[0] = 0.0;hranges[1] = 255.0;ranges[0] = hranges;channels[0] = 0;}cv::MatND getHistogram(const cv::Mat &image);cv::Mat getHistogramImage(const cv::Mat &image);cv::Mat applyLookUp(const cv::Mat &image, const cv::Mat &lookup);cv::Mat stretch(const cv::Mat &image, int minValue = 0);};
//类中的方法#include "stdafx.h"#include "Histogram1D.h"cv::MatND Histogram1D::getHistogram(const cv::Mat &image){cv::MatND hist;cv::calcHist(&image, 1, channels, cv::Mat(), hist, 1, histSize, ranges);return hist;}cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image){cv::MatND hist = getHistogram(image);double maxVal;double minVal;cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);cv::Mat histImg(histSize[0], histSize[0], CV_8U, cv::Scalar(255));int hpt = static_cast<int>(0.9 * histSize[0]);for (int h = 0; h < histSize[0]; h++){float binVal = hist.at<float>(h);int intensity = static_cast<int>(binVal * hpt / maxVal);cv::line(histImg, cv::Point(h, histSize[0]), cv::Point(h, histSize[0] - intensity), cv::Scalar::all(0));}return histImg;}cv::Mat Histogram1D::applyLookUp(const cv::Mat &image, const cv::Mat &lookup){cv::Mat result;cv::LUT(image, lookup, result);return result;}cv::Mat Histogram1D::stretch(const cv::Mat &image, int minValue){cv::MatND hist = getHistogram(image);cv::Mat result;int imin = 0, imax = histSize[0] - 1, dim = 256;for (; imin < histSize[0]; imin++){if (hist.at<float>(imin) > minValue){break;}}for (; imax >= 0; imax--){if (hist.at<float>(imax) > minValue){break;}}cv::Mat lut(1, &dim, CV_8U);for (int i = 0; i<256; i++){if (i < imin) lut.at<uchar>(i) = 0;else if (i > imax) lut.at<uchar>(i) = 255;else lut.at<uchar>(i) = static_cast<uchar>(255.0*(i - imin) / (imax - imin) + 0.5);}result = applyLookUp(image, lut);return result;}
//主函数#include "stdafx.h"#include <opencv2\opencv.hpp>#include "Histogram1D.h"int main(){cv::Mat image = cv::imread("F:\\group.jpg", 0);Histogram1D h;int dim = 256;cv::Mat lut(1, &dim, CV_8U);for (int i = 0; i < 256; i++){lut.at<uchar>(i) = 255 - i;}cv::imshow("Original image", image);cv::imshow("Original form", h.getHistogramImage(image));cv::imshow("Negative image", h.applyLookUp(image, lut));cv::imshow("Stretched image", h.stretch(image, 100));cv::imshow("Stretched form", h.getHistogramImage(h.stretch(image, 100)));cv::waitKey(0); return 0;}
可以粘到IDE上先看看,然后再看文字,效果能更好
- OpenCV2编程手册笔记之 4.3查找表修改图像外观
- opencv2使用查找表修改图像外观
- opencv2—(8)查找表修改图像外观
- OpenCV2编程手册笔记之 2.3指针遍历图像
- OpenCV2编程手册笔记之 2.4迭代器遍历图像
- OpenCV2编程手册笔记之 4.2计算图像的直方图
- OpenCV学习笔记(六):使用查找表修改图像外观
- OpenCV2编程手册笔记之 5.2形态学滤波对图像进行腐蚀、膨胀运算
- OpenCV2编程手册笔记之 5.3形态学滤波对图像进行开闭运算
- OpenCV2编程手册笔记之 5.5分水岭算法对图像进行分割
- OpenCV2编程手册笔记之 4.2计算图像的直方图(彩色)
- OpenCV2编程手册笔记之 4.5反投影直方图以检测特定图像内容
- OpenCV2编程手册笔记之 6.5计算图像的拉普拉斯变换
- OpenCV2编程手册笔记之 5.6GrabCut提取前景
- OpenCV2编程手册笔记之 2.2存取像素值
- OpenCV2编程手册笔记之 4.4直方图均衡化
- OpenCV2编程手册笔记之 6.2使用低通滤波器
- OpenCV2编程手册笔记之 6.3中值滤波器
- TensorFlow softmax VS sparse softmax
- HSV颜色空间中的肤色检测
- String与StringBuffer以及StringBuilder的异同点
- leetcode:561. Array Partition I
- 编码,UTF8,UNICODE
- OpenCV2编程手册笔记之 4.3查找表修改图像外观
- JavaScript排序方法
- Linus实验楼笔记——第12节:数据流重定向
- C#--虚方法的使用
- Java数组中常见的面试题
- 性能优化1-内存泄漏
- 面试题-Java基础-集合和数组
- 【083】深度学习读书笔记:P26特征分解的证明
- java数组详解