图像处理 对比度拉伸变换

2020-01-08 16:37:42 qq_38344751 阅读数 84

对比度拉伸变换  对图像进行对比度拉伸变换,压缩动态范围,将我们所关注的边界特征信息详细化,从而使得输出图像亮区域更亮,暗区域更暗,提高了图像的对比度。

opencv中的  LUT函数(look up table)为查表函数,

void LUT(InputArray src, InputArray lut, OutputArray dst);

InputArray src:输入图像

OutputArray dst:输出图像

InputArray lut:查找表

#include<opencv2/opencv.hpp>
#include<iostream>
#include<string>
#include<vector>
using namespace std;
using namespace cv;

void contrastStretch(Mat &img)
{
	if (img.empty())
	{
		cerr << "image empty" << endl;
		return;
	}
	// 计算图像的最大最小值
	double pixMin, pixMax;
	minMaxLoc(img, &pixMin, &pixMax);

	//create lut table
	Mat lookut(1, 256, CV_8U);
	for (int i = 0; i < 256; i++)
	{
		if (i < pixMin)
			lookut.at<uchar>(i) = 0;
		else if (i > pixMax)
			lookut.at<uchar>(i) = 255;
		else 
			lookut.at<uchar>(i) = static_cast<uchar>(255.0*(i - pixMin) / (pixMax - pixMin) + 0.5);
	}
	LUT(img, lookut, img); //(look up table)即为查表函数
}

int main()
{
	Mat srcImage = imread(img_name,1);
	if (!srcImage.data)
		return 0;
	Mat resultImage;

	vector<Mat> channel;
	split(srcImage, channel);
	contrastStretch(channel[0]);
	contrastStretch(channel[1]);
	contrastStretch(channel[2]);
	merge(channel, resultImage);//合并3个通道

	imshow("srcImage", srcImage);
	imshow("resultImage", resultImage);
	waitKey(0);

	return 0;
}

结果如下,图像变得更加对比清晰

 

2011-11-23 15:31:18 honesty2008 阅读数 9021

实验题目:

根据下图参考数据和图像,编程实现数字图像的对比度拉伸。

实验分析:

根据上图,可得:我们只要把图形中灰度值为28-75的像素点修改灰度值即可以完成本次实验。
可以先找出28,75的纵坐标,根据两点式求出该范围内的直线方程。
如设两点坐标为(x0,y1),(x1,y1),则斜率为(y1-y0)/(x1-x0)。

实验程序: lab1.m

function lab1(addr,x1,y1,x2,y2)
%功能:完成实验一,灰度拉伸处理
% addr 为要处理的图片的文件名,默认为images\sy1.jpg
% x1,y1,x2,y2 为拉伸处理的线段端点坐标,当参数小于5个时
% 这些坐标均采用默认值,可以直接按 F5 运行。
if nargin<1
    addr='images\sy1.jpg';
end
if nargin<5
    x1=28;y1=28;
    x2=75;y2=255;
end
if  x1==x2
    display('x1、x2不能相同,退出程序');
    return ;
end
I=imread(addr);
[r,c,n]=size(I);
k=(y1-y2)/(x1-x2);
b=y1-k*x1;
if n>1
    I2=rgb2gray(I);
else I2=I;
end
I2=double(I2);
for x=1:r
    for y=1:c
        tmp=I2(x,y);
        if tmp>=x1 && tmp<=x2
            I2(x,y)=k*tmp+b;
        end
    end
end
subplot(1,2,1);imshow(I);title('original image ');
subplot(1,2,2);imshow(I2,[]);title('image after modification');



2015-10-22 14:48:44 qq_15096707 阅读数 13635

这次我们要处理的是对图像进行旋转操作,具体要求,如下:

       自定义一个图像的仿射变换函数,用于旋转给定的输入图像,该函数的输入参数包括处理前的图像和旋转角度。输入的角度为正数,表明处理结果为顺时针旋转,负数则为逆时针旋转,输出参数为处理后的图像。

       曾参考《数字图像处理(第三版)》一书中P51的公式编写过自己的图像“旋转”函数,但是在某些角度下,输出结果却发生了错误,至于原因,也由于时间关系,仍未思考出来。使用Matlab编程,原代码如下:

%自己写的函数
function []=myRotation(pho,angle)
im1=imread(pho);
subplot(121);
imshow(im1);
title('输入图像');
im1=double(im1);
[r,c,h]=size(im1);
 
R=angle*pi/180;
h2 = ceil(r*cos(R)+c*sin(R));
w2 = ceil(r*sin(R)+c*cos(R));
im2=zeros(h2,w2,h);
 
T=[sin(R) cos(R); cos(R) -sin(R)];
%invT=inv(T);
for i=1:h
    for x=1:h2
        for y=1:w2
            temp=([x y]-[0 r*sin(R)])/T;
            temp(1)=ceil(temp(1));
            temp(2)=ceil(temp(2));
            if temp(2)>0 && temp(2)<=r && temp(1)>0 && temp(1)<=c
                im2(x,y,i)=im1(temp(2),temp(1),i);
            end
        end
    end
end
subplot(122);
imshow(uint8(im2));
title('输出图像');

       另外,采用了一种方法(参考 点击打开链接),同样使用推导出来的公式,采用反向映射的方法,结合双线性内插,得出旋转后的图像。但是得出来的结果,如输入 180°,没有出现输出结果。参考后修改的程序如下:

function []=myRotation3(pho,angle)
im1=imread(pho);
im1=double(im1);
[m,n,h]=size(im1);
 
R = angle*pi/180;   %旋转角度
%新图像大小
m2 = ceil(m*cos(R)+n*sin(R));
n2 = ceil(m*sin(R)+n*cos(R));
 
u0= m*sin(R);%平移量
 
%变换矩阵   
T=[cos(R),sin(R);-sin(R),cos(R)];
L = zeros(m2,n2);
for i=1:h
    for u=1:n2
      for v=1:m2
        %新图像坐标变换到原图像坐标x和y中
        temp = T*([u;v]-[u0;0]);
        x= temp(1);
        y= temp(2);
        if x>=1 & x<=m & y>=1 & y<=n    %若变换出的x和y在原图像范围内
            x_low=floor(x);
            x_up=ceil(x);
            y_low=floor(y);
            y_up=ceil(y);
 			%双线性内插值
            p1=im1(x_low,y_low,i);
            p2=im1(x_up,y_low,i);
            p3=im1(x_low,y_low,i);
            p4=im1(x_up,y_up,i);
            s=x-x_low;
            t=y-y_low;
            L(u,v,i)=(1-s)*(1-t)*p1+(1-s)*t*p3+(1-t)*s*p2+s*t*p4;
        end
      end
    end
end
 
imshow(uint8(L));
title('输出图像');

而正确程序代码,则是通过研究参考 图像旋转算法原理点击打开链接),在只有原理的情况下,研究透,将其转化为 程序。MATLAB代码如下:

%这个旋转才没有bug
function []=myRotation(pho,angle)
im1=imread(pho);
subplot(121);
imshow(im1);
title('输入图像');
im1=double(im1);
[r,c,h]=size(im1);
 
%将角度单位化为弧度单位
R=-angle*pi/180;
%这样的宽高会出现BUG,原因不明
%h2 = ceil(r*cos(R)+c*sin(R));
%w2 = ceil(r*sin(R)+c*cos(R));
 
%将对角线作为旋转后图像的宽高
h2=ceil(sqrt(r*r+c*c));
w2=h2;
 
im2=zeros(h2,w2,h);
 
%旋转时x y的偏移量
dx=-0.5*w2*cos(R)-0.5*h2*sin(R)+0.5*c;
dy=0.5*w2*sin(R)-0.5*h2*cos(R)+0.5*r;
 
%采用反向映射
for i=1:h
    for x=1:h2
        for y=1:w2
            %由结果图像的坐标 得出 原来图像的坐标
            x0=ceil(x*cos(R)+y*sin(R)+dx); 
            y0=ceil(-x*sin(R)+y*cos(R)+dy);
            
            if x0>0 && x0<=r && y0>0 && y0<=c
                im2(x,y,i)=im1(x0,y0,i);
            end
        end
    end
end
%显示图像
subplot(122);
imshow(uint8(im2));
title('输出图像');


旋转45°——> myRotation('实验2_lena.bmp',45),结果如下:


旋转-45°——> myRotation('实验2_lena.bmp',-45),结果如下:


图像反色处理

       自定义一个函数,将输入图像进行反色处理,该函数输入参数为处理前的图像,输出参数为处理后的图像。

Matlab编程,代码如下:

function []=myFanse(pho)
im1 = imread(pho);
subplot(121);
imshow(im1);
title('输入图像');
im1 = double(im1);
[r c m] = size(im1);
im2 = zeros(r,c,m);
for i=1:m
for j=1:r
for k=1:c
im2(j,k,i)=255-im1(j,k,i); %由最高灰度级减去原坐标位置的灰度级进行反色
end
end
end
im2 = uint8(im2);
subplot(122);
imshow(im2);
title('输出图像');
       当然,其实也可以利用Matlab中的矩阵运算编写程序,这样程序可以更加精简,这里就不给出了。   

       myFase('实验2_lena.bmp'),运行结果如下:


图像对比度拉伸变换

  自定义一个图像的对比度拉伸函数,将输入图像的对比度拉伸到指定的灰度级区间,该函数的输入参数包括处理前的图像、期望灰度级区间的最小值和最大值(如指定区间为[50 200]),输出参数为处理后的图像。

Matlab代码如下:

function []=myContrConver(pho, mi, ma)
im1 = imread(pho);
subplot(121);
imshow(im1);
title('输入图像');
im1 = double(im1);
[r c m] = size(im1);
im2 = zeros(r,c,m);
%for i=1:m
%    for j=1:r
%        for k=1:c
%            im2(j,k,i)=min+(im1(j,k,i)-minR)/(maxR-minR)*(max-min);
%        end
%    end
%end
 
%先对原图像的 灰度级 进行归一化,再由归一化的区间缩放至所需区间
tempIma1=im1(:,:,1);
tempIma2=im1(:,:,2);
tempIma3=im1(:,:,3);
im2(:,:,1)=mi+(im1(:,:,1)-min(tempIma1(:)))/(max(tempIma1(:))-min(tempIma1(:)))*(ma-mi);
im2(:,:,2)=mi+(im1(:,:,2)-min(tempIma2(:)))/(max(tempIma2(:))-min(tempIma2(:)))*(ma-mi);
im2(:,:,3)=mi+(im1(:,:,3)-min(tempIma3(:)))/(max(tempIma3(:))-min(tempIma3(:)))*(ma-mi);
 
im2=uint8(im2);
subplot(122);
imshow(im2);
title('输出图像');


       myContrConver('实验2_lena.bmp'),运行结果如下:



2019-07-17 15:38:42 space_walk 阅读数 862

一幅图像中,最高灰度级和最低灰度级的差成为对比度。一幅低对比度的图像,看起来细节会少很多。可以通过对比度拉伸提高图像对比度,显示更多细节。先来看看对比度拉伸的典型变换:
对比度拉伸典型变换
书本中(冈萨雷斯:数字图像处理第三版P69)的对比度拉伸变换函数图是这样的:

书中对比度拉伸变换函数图
图3.10(b)低对比度拉伸图中,最低灰度级为91,最高灰度级为138,并且要将灰度值拉伸至[0, 255]。阈值处理的函数的图像即为P64图3.2第二个图像,其中k = 109。
实验代码如下:

% 读入图像
img_1 = imread('Fig0310(b)(washed_out_pollen_image).tif');

% max():返回一个行向量,向量的第i个元素是矩阵A的第i列上的最大值。
% 再一次即可求得最高灰度级
r_max = max(max(img_1));
%max() 同理
r_min = min(min(img_1));

% 求输入图像的尺寸
[r, c] = size(img_1);

% 生成两张0图,一张用于对比度拉伸,一张用于阈值处理
img_2 = zeros(r, c);
img_3 = zeros(r, c);

% 将输入图像转换成double型
img_1s = double(img_1);

% 计算斜率
k = (255 - 0) / (r_max - r_min);
% 灰度级总和
sum = 0;

for x = 1 : r
    for y = 1 : c
        % 对每个像素点进行拉伸,并赋值到新图像
        img_2(x, y) = k * (img_1s(x, y) - r_min);
        % 求灰度级总和
        sum = sum + img_1s(x, y);
    end
end

% 求阈值,这里阈值为平均值
avg = sum / (r * c);

% 阈值处理
for x = 1 : r
    for y = 1 : c
        % 小于阈值赋值0
        if img_1s(x, y) < avg
             img_3(x, y) = 0;
         % 大于阈值赋值1
        else
            img_3(x, y) = 1;
        end
    end
end

% 转换
img_2 =  im2uint8(mat2gray(img_2));
img_3 =  im2uint8(mat2gray(img_3));
% 显示
subplot(131), imshow(img_1);
subplot(132), imshow(img_2);
subplot(133), imshow(img_3);

结果如下:
结果对比

2016-08-04 20:17:28 hhw999 阅读数 4820


对数及对比度拉伸变换



对数和对比度拉伸变换是:动态范围操作的基本工具

表达式:g=c*log(1+f),其中c是一个常数,f是浮点数

对数变换:
               应用:压缩动态范围(实现了图像灰度扩展和压缩功能,扩展低灰度值而压缩高灰度值,让图像的灰度分布更加符合人的视觉特性)(灰度值0(黑)~255(白))
                         可以利用这种变换来扩展被压缩的高值图像中的暗像素
     
               mat2gray(f):会将压缩值限定在【0,1】范围

               im2uint8( mat2gray(f) ):会将值限定在【0,255】范围

对比度拉伸变换函数:把窄的输入灰度级扩展为宽的范围的输出灰度级,结果是一幅高对比度的图像
                  表达式:                  1
                            s=T(r)=   - - - - - - -     ,
                                          1+(m/r)^E
                            其中r为输入图像的灰度,s是输出图像中的相应灰度值,E用于控制该函数的斜率

阈值化/阈值处理函数:用于图像分割的简单工具