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上先看看,然后再看文字,效果能更好

阅读全文
0 0