MATLAB实现ENVI2%线性拉伸
一. MATLAB实现ENVI线性拉伸
1.参考链接,程序主体来源于:
https://blog.csdn.net/u014090429/article/details/106403645
2.程序修改适用于RGB影像
(1)修改内容介绍:
修改1:适用于影像不完全覆盖矩形区域,即存在大量无效值区域的影像。
修改2:ENVI对影像进行线型拉伸,是针对每一波段的影像进行线性拉伸的。(即分别对R,G,B波段进行拉伸)。原程序适用于单波段处理,修改后程序适用于RGB影像。
(2)程序介绍:
程序包含3个函数:
(1)calc_lr_val.m(计算影像的灰度直方图)
(2)img_map.m(将原影像按照2%线性拉伸投射到uint8的影像)
(3)img_strech.m(线性拉伸应用到RGB影像上)
(4)程序使用例子
% ------------------------------------
% 计算直方图左右裁剪的灰度值
% 2015/07/01
%
% Input histcount --> 直方图
% tt --> 图像像素个数
% per --> 左右裁剪的百分比
%
% Output l_val --> 左值
% r_val --> 右值
% ------------------------------------
function [l_val, r_val] = calc_lr_val(histcount, tt, per)
fprintf(' ... ... ... ... ... ... ... ... ...\n');
fprintf(' ... CALC LEFT AND RIGHT VALUE \n');
per_tt = tt*per; % 按百分比裁剪的像素个数
% 计算左值
tmp = 0;
for i = 1:length(histcount)
tmp = tmp + histcount(i);
if tmp >= per_tt
l_val = i;
break;
end
end
% 计算右值
tmp = 0;
for i = 1:length(histcount)
tmp = tmp + histcount(length(histcount)-i+1);
if tmp >= per_tt
r_val = length(histcount)-i+1;
break;
end
end
fprintf(' ... Stretch Percentage is %d%%\n', per*100);
fprintf(' ... Left Val is %d \n', l_val);
fprintf(' ... Right Val is %d \n', r_val);
fprintf(' ... ... ... ... ... ... ... ... ...\n\n');
return
% ------------------------------------
% 将图像映射至 [0, 255] 区间
% 2015/07/01
%
% Input img_16bit --> 16位原图像
% l_val --> 映射左值
% r_val --> 映射右值
%
% Output img_8bit --> 输出8位拉伸后图像
% ------------------------------------
function [img_8bit] = img_map(img_16bit, l_val, r_val)
[xlen, ylen, c] = size(img_16bit);
img_8bit = zeros(xlen, ylen);
fprintf(' ... ... ... ... ... ... ... ... ...\n');
fprintf(' ... IMG MAPPING FROM 16BIT TO 8BIT \n');
fprintf(' ... Img mapping begin ... ... \n');
% 按照左右值映射
img_8bit = (img_16bit - l_val).*(255/(r_val-l_val));
img_8bit = uint8(round(img_8bit));
fprintf(' ... Img mapping finshied !!! !!! \n\n');
return
function img_matrx_new= img_strech(img_file_name)
img_matrix = imread(img_file_name);
for i=1:3
img=img_matrix(:,:,i);
% 这里默认输入图像为单通道
[ylen, xlen] = size(img);
% fprintf(' ... Img Xlen: %d pixels\n', xlen);
% fprintf(' ... Img Ylen: %d pixels\n\n\n', ylen);
% 线性拉伸
max_val = max(img(:));
%img(find(img<=1))=nan;
min_val = min(img(:));
% temp_img=img(:);
% min_val = min(temp_img(find(temp_img~=0)));
% %b=min(B(find(B~=0)));
% fprintf(' ... ... ... ... ... ... ... ... ... ...\n');
% fprintf(' ... Min Val is %d \n', min_val);
% fprintf(' ... Max Val is %d \n', max_val);
% fprintf(' ... ... ... ... ... ... ... ... ... ...\n\n');
% 统计直方图
% 输入图像为16位,取值范围为 0 到 65535
bins = 0:65535;
histcount = histc(img(:)', bins);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
histcount(1) =0; %因为自己使用的影像,有很多nodata_value,但是数值为0,所以加这一步骤
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%清除临时变量
clear bins max_val min_val;
% 直方图裁剪,计算左值和右值
[l_val, r_val] = calc_lr_val(histcount, xlen*ylen, 0.02);
% 根据左值和右值,将图像由16位映射至8位
img_8bit = img_map(img, l_val, r_val);
% 保存结果
img_matrx_new(:,:,i)=img_8bit;
%imwrite(img_8bit, 'res_blue.png');
end
% return (img_matrx_new);
end
%RGB影像:band 1,2,3 分别是 R,G,B
img_file_name='E:\2022_5_2_GF_pa1_pa2_lens_rect\pa2_021_010\树高查看\layer_stcak_ms.tif';
img_strech_new= img_strech(img_file_name);
imshow(img_strech_new);
展示结果,目视和envi展示结果一致:
二.matlab在底图上画剖面线
1.在底图上画剖面线
参考链接:https://blog.csdn.net/Enjolras_fuu/article/details/66530196
想要的结果:底图上有两条线,且坐标都在。
我的流程:
fclose all
clear all
clc
%RGB影像:band 1,2,3 分别是 R,G,B
img_file_name='E:\2022_5_2_GF_pa1_pa2_lens_rect\pa2_021_010\树高查看\layer_stcak_ms.tif';
img_strech_new= img_strech(img_file_name);
%imshow(img_strech_new);
chm_name='E:\2022_5_2_GF_pa1_pa2_lens_rect\pa2_021_010\树高查看\layer_stcak_chm.tif';
img_chm=imread(chm_name);
size_img_chm=size(img_chm);
y_axis_limits=[-50,50];
figure();
hold on
imshow(img_strech_new);
hold on
show_y=ones(1,size_img_chm(2))*(ceil(size_img_chm(1)/2))+(-img_chm(ceil(size_img_chm(1)/2),:));
plot(show_y,'r','LineWidth',2);
hold on
plot(ones(1,size_img_chm(2))*(ceil(size_img_chm(1)/2)),'k','LineWidth',1);
%axis xy
hold on
%axis([0 size_img_chm(2) y_axis_limits(1) y_axis_limits(2)]);%限制x轴,y轴的显示范围
axis on
axis([0 size_img_chm(2) 0 size_img_chm(1)]);%限制x轴,y轴的显示范围
hold off
2.底图上的剖面线与底图表示为不同的坐标系
双坐标系参考:https://blog.csdn.net/qq_20481015/article/details/81172140
fig=figure;
%先用imshow画出底图
imshow(img_strech_new);
hold on
%激活左边的坐标系,作为底图,或者是第一个plot的坐标系
yyaxis left
plot(ones(1,size_img_chm(2))*(chm_show_line),'y','LineWidth',1);
hold on
%限制左边坐标系的显示范围
axis([0 size_img_chm(2) 0 size_img_chm(1)]);%限制x轴,y轴的显示范围
axis on
%激活右边的坐标系,作为第二个plot的坐标系
yyaxis right
set(gca,'YDir','normal'); %将y轴方向设置为普通(从下到上递增)。
%set(gca,'YDir','reverse'); %将x轴方向设置为反向(从上到下递增)。
show_y=(img_chm(chm_show_line,:)+7);
%show_y=ones(1,size_img_chm(2))*(chm_show_line)+(img_chm(chm_show_line,:)+7);
plot(show_y,'r','LineWidth',2);
hold on
%限制右边坐标系的显示范围
axis([0 size_img_chm(2) -(1-chm_show_line/size_img_chm(1))*100 (chm_show_line/size_img_chm(1))*100]);%限制x轴,y轴的显示范围
axis on