图像灰度拉伸
1 原理
图像灰度拉伸是改变图像对比度的一种方法,通过灰度映射,将原图中某一区段中的灰度值映射到另一灰度值,从而拉伸或压缩整个图像的灰度分布范围。
2 Matlab实现
clc;
clear;
close all;
% 对灰度图进行灰度线性变换
ori_img = imread('../images/6.jpg');
ori_img1 = rgb2gray(ori_img);
[oriHist,oriX] = imhist(ori_img1);
pt0 = [0,0];
pt1 = [100,50];
pt2 = [150,160];
pt3 = [255,200];
[width,height] = size( ori_img1);
gray1 = ori_img1;
for i=1:1:width
for j = 1:1:height
if (gray1(i,j)<pt1(1))
gray1(i,j) = pt0(2) + (gray1(i,j)-pt0(1)) * ((pt1(2)-pt0(2))/(pt1(1)-pt0(1)));
else if(gray1(i,j)>=pt1(1)&&gray1(i,j)<pt2(1))
gray1(i,j) = pt1(2) + (gray1(i,j)-pt1(1)) * ((pt2(2)-pt1(2))/(pt2(1)-pt1(1)));
else
gray1(i,j) = pt2(2) + (gray1(i,j)-pt2(1)) * ((pt3(2)-pt2(2))/(pt3(1)-pt2(1)));
end
end
end
end
[g1Hist,g1X] = imhist(gray1);
figure(1),subplot(1,2,1),imshow(ori_img1),title('原图');subplot(1,2,2),imshow(gray1),title('灰度线性拉伸');
figure(2),subplot(1,2,1),stem(oriX,oriHist),title('原图直方图');subplot(1,2,2),stem(g1X,g1Hist),title('灰度线性拉伸直方图');
3 OpenCV实现
//
int cvPointCmp(cv::Point& a, cv::Point& b)
{
return a.x < b.x;
}
//根据控制点,生成灰度拉伸所使用的查找表
void CreateLSLUT(std::vector<cv::Point>& pts, cv::Mat& lut)
{
if (pts.size() == 0)
return;
//在控制点前增加(0,0)点,末尾增加(255,255)点
std::vector<cv::Point> npts(1, cv::Point(0, 0));
npts.insert(npts.end(), pts.begin(), pts.end());
npts.push_back(cv::Point(255, 255));
//根据点的X坐标排序
std::sort(npts.begin(), npts.end(), cvPointCmp);
lut = cv::Mat(1, 256, CV_8UC1);
int nLoc = 0;
for (int i = 0; i < 256; i++)
{
for (int j = nLoc; j < npts.size()-1; j++)
{
//找出i所对应的区间的端点,左闭右开区间
if (npts[j].x <= i && npts[j+1].x > i)
{
nLoc = j;
float y = npts[j].y + 1.0*(npts[j + 1].y - npts[j].y) / (npts[j + 1].x - npts[j].x)*(i - npts[j].x);
if (y < 0)
y = 0;
if (y > 255)
y = 255;
lut.at<uchar>(i) = (uchar)y;
break;
}
}
}
}
#include "../include/baseOps.h"
#include <iostream>
#include <string>
#include "../include/opencv400/opencv2/opencv.hpp"
#include "windows.h"
int main()
{
SetCurrentDirectoryToExePath();
cv::Mat ori_img = cv::imread("../images/6.jpg");
cv::Mat gray_img;
cv::cvtColor(ori_img, gray_img, cv::COLOR_BGR2GRAY);
cv::namedWindow("灰度图");
cv::imshow("灰度图", gray_img);
cv::Mat grayHist;
calcHist1D(gray_img, grayHist);
cv::imshow("hist", grayHist);
//确定控制点
std::vector<cv::Point> pts;
pts.push_back(cv::Point(50, 100));
pts.push_back(cv::Point(100, 80));
pts.push_back(cv::Point(80, 120));
pts.push_back(cv::Point(250, 80));
//生成灰度映射表
cv::Mat lut;
CreateLSLUT(pts, lut);
//查表操作
cv::Mat res;
cv::LUT(gray_img, lut, res);
cv::Mat g1Hist;
calcHist1D(res, g1Hist);
cv::imshow("g1", res);
cv::imshow("g1Hist", g1Hist);
cv::waitKey();
return 0;
}