【圖像處理】-004 圖像灰度拉伸

圖像灰度拉伸

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;
}

4 效果

在這裏插入圖片描述在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章