【图像处理】金属器件高亮度图像处理

news/2024/7/21 7:41:39 标签: 图像处理, matlab, 计算机视觉

金属器件高亮度图像处理

  • 一、RGB颜色空间向YCbCr空间转化
  • 二、归一化处理
  • 三、直方图均衡化
  • 四、分段线性变换

前言:在制作数据集时,发现对于金属器件的拍摄图像,或多或少存在一定高曝光问题,本文章针对此问题提供一种解决方式

一、RGB颜色空间向YCbCr空间转化

对一种颜色进行编码的方法统称为颜色空间最常用的表现彩色图像的颜色空间是 RGB 颜色空间。

在该颜色空间中,颜色被定义为由 R,G,B 3个分量组成。这 3 个分量都包含了亮度信息它们之间存在着很大的相关性,而这种相关性,加大了高光处理的难度。

这里用到的颜色空间 YCbCr 是亮度和色度分离的颜色空间 YUV的一种YUV 是被欧洲电视系统所采用的一种颜色编码方法,其中,Y 表示亮度, 和V表示的则是色度。

本算法选择 YCbCr 作为去除高光算法的基础,Y 代表图像的亮度信息,Cb 指蓝色色度分量,而 Cr 指红色色度分量Cb,该颜色空间将 RGB 分解成亮度空间。

matlab">	I = imread(filename);
	I_YUV = rgb2ycbcr(I);

    %% 显示Y通道图像
	figure;
    Y = I_YUV(:,:,1);
    % imhist(Y)
    imshow(Y);
    title("原图像");

结果图

在这里插入图片描述

二、归一化处理

归一化处理是为了使得函数的曲线更加清晰,也更容易计算。

matlab">    %% 归一化为[0 1]
    desiredMin = 0;     %想要的最小灰度
    desiredMax = 1;     %想要的最大灰度
    desiredRange = desiredMax - desiredMin;
    dblImageS1 = desiredRange*(double(Y) - originalMinValue) / originalRange+desiredMin;
    figure;
    imhist(dblImageS1);
    title('归一化直方图');

结果图

在这里插入图片描述

三、直方图均衡化

这里直方图均衡化使用了matlab自带的histeq,因为只对Y通道进行处理,所以相当于是对灰度值进行处理,均衡化效果也比较不错。

matlab">    %% 直方图均衡化
    % hist_img = hist_img(dblImageS1);
    subplot(143)
    % imhist(hist_img);
    J = histeq(dblImageS1);  %直方图均衡化
    I_YUV(:,:,1) = J;
    % imhist(J)
    imshow(J);
    title("均衡化图像")

结果图

在这里插入图片描述

可以看到,均衡化后的效果已经好很多了。

四、分段线性变换

分段的灰度拉伸可以更加灵活的控制输出灰度直方图的分布,可以有选择性的拉伸某段灰度区间,以改善输出图像。如果一副图像集中在较暗的区域而导致图像偏暗。

可以用灰度拉伸功能来扩展(斜率>1)物体的灰度区间以改善图像;同样,如果图像的灰度集中在较亮的区域而导致图像偏亮,也可以用灰度拉伸功能来压缩(斜率小于1)物体灰度区间以改善图像质量。

这里使用了自定义函数函数imgrayscaling
在这里插入图片描述

matlab">%%
function out = imgrayscaling(varargin)
    % IMGRAYSCALING     执行灰度拉伸功能
    %   语法:
    %       out = imgrayscaling(I, [x1,x2], [y1,y2]);
    %       out = imgrayscaling(X, map, [x1,x2], [y1,y2]);
    %       out = imgrayscaling(RGB, [x1,x2], [y1,y2]);
    %   这个函数提供灰度拉伸功能,输入图像应当是灰度图像,但如果提供的不是灰度
    %   图像的话,函数会自动将图像转化为灰度形式。x1,x2,y1,y2应当使用双精度
    %   类型存储,图像矩阵可以使用任何MATLAB支持的类型存储。
    
    [A, map, x1 , x2, y1, y2] = parse_inputs(varargin{:});
    
    % 计算输入图像A中数据类型对应的取值范围
    range = getrangefromclass(A);
    range = range(2);
    
    % 如果输入图像不是灰度图,则需要执行转换
    if ndims(A)==3,% A矩阵为3维,RGB图像
          A = rgb2gray(A);
        elseif ~isempty(map),% MAP变量为非空,索引图像
          A = ind2gray(A,map);
    end % 对灰度图像则不需要转换
     
    % 读取原始图像的大小并初始化输出图像
    [M,N] = size(A);
    I = im2double(A);		% 将输入图像转换为双精度类型
    out = zeros(M,N);
     
    % 主体部分,双级嵌套循环和选择结构
    for i=1:M
        for j=1:N
            if I(i,j)<x1
                out(i,j) = y1 * I(i,j) / x1;
            elseif I(i,j)>x2
                out(i,j) = (I(i,j)-x2)*(range-y2)/(range-x2) + y2;
            else
                out(i,j) = (I(i,j)-x1)*(y2-y1)/(x2-x1) + y1;
            end
        end
    end
    
    % 将输出图像的格式转化为与输入图像相同
    if isa(A, 'uint8') % uint8
            out = im2uint8(out);
        elseif isa(A, 'uint16')
            out = im2uint16(out);
        % 其它情况,输出双精度类型的图像
    end
    
     % 输出:
    if nargout==0 % 如果没有提供参数接受返回值
      imshow(out);
      return;
    end
end


%%
function [A, map, x1, x2, y1, y2] = parse_inputs(varargin);
    % 这就是用来分析输入参数个数和有效性的函数parse_inputs
    % A       输入图像,RGB图 (3D), 灰度图 (2D), 或者索引图 (X)
    % map     索引图调色板 (:,3)
    % [x1,x2] 参数组 1,曲线中两个转折点的横坐标
    % [y1,y2] 参数组 2,曲线中两个转折点的纵坐标
    % 首先建立一个空的map变量,以免后面调用isempty(map)时出错
    map = [];
     
    %   IPTCHECKNARGIN(LOW,HIGH,NUM_INPUTS,FUNC_NAME) 检查输入参数的个数是否
    %   符合要求,即NUM_INPUTS中包含的输入变量个数是否在LOW和HIGH所指定的范围
    %   内。如果不在范围内,则此函数给出一个格式化的错误信息。
    iptchecknargin(3,4,nargin,mfilename);
     
    %   IPTCHECKINPUT(A,CLASSES,ATTRIBUTES,FUNC_NAME,VAR_NAME, ARG_POS) 检查给定
    %   矩阵A中的元素是否属于给定的类型列表。如果存在元素不属于给定的类型,则给出
    %   一个格式化的错误信息。
    iptcheckinput(varargin{1},...
                  {'uint8','uint16','int16','double'}, ...
                  {'real', 'nonsparse'},mfilename,'I, X or RGB',1);
     
    switch nargin
     case 3 %            可能是imgrayscaling(I, [x1,x2], [y1,y2]) 或 imgrayscaling(RGB, [x1,x2], [y1,y2])
      A = varargin{1};
      x1 = varargin{2}(1);
      x2 = varargin{2}(2);
      y1 = varargin{3}(1);
      y2 = varargin{3}(2);
     case 4
      A = varargin{1};%               imgrayscaling(X, map, [x1,x2], [y1,y2])
      map = varargin{2};
      x1 = varargin{2}(1);
      x2 = varargin{2}(2);
      y1 = varargin{3}(1);
      y2 = varargin{3}(2);
    end
    
    % 检测输入参数的有效性
    % 检查RGB数组
    if (ndims(A)==3) && (size(A,3)~=3)   
        msg = sprintf('%s: 真彩色图像应当使用一个M-N-3维度的数组', ...
                      upper(mfilename));
        eid = sprintf('Images:%s:trueColorRgbImageMustBeMbyNby3',mfilename);
        error(eid,'%s',msg);
    end
     
    if ~isempty(map) 
    % 检查调色板
      if (size(map,2) ~= 3) || ndims(map)>2
        msg1 = sprintf('%s: 输入的调色板应当是一个矩阵', ...
                       upper(mfilename));
        msg2 = '并拥有三列';
        eid = sprintf('Images:%s:inColormapMustBe2Dwith3Cols',mfilename);
        error(eid,'%s %s',msg1,msg2);
        
      elseif (min(map(:))<0) || (max(map(:))>1)
        msg1 = sprintf('%s: 调色板中各个分量的强度 ',upper(mfilename));
        msg2 = '应当在0和1之间';
        eid = sprintf('Images:%s:colormapValsMustBe0to1',mfilename);
        error(eid,'%s %s',msg1,msg2);
      end
    end
     
    % 将int16类型的矩阵转换成uint16类型
    if isa(A,'int16')
      A = int16touint16(A);
    end
end

调用函数时,使用imgrayscaling(J, [x1, x2], [y1, y2]);

结果图

在这里插入图片描述

以上是个人理解,如有错误欢迎指出!


http://www.niftyadmin.cn/n/159109.html

相关文章

Web自动化——前端基础知识(二)

1. Web前端开发三要素 web前端开发三要素 什么是HTMl&#xff1f; Html是超文本标记语言&#xff0c;是用来描述网页的一种标记语言HTML是一种标签规则的形式将内容呈现在浏览器中可以以任意编辑器创建&#xff0c;其文件扩展名为.html或.htm保存即可 什么是CSS&#xff1f;…

SIMBAR论文精读

SIMBAR&#xff1a;用于自动驾驶视觉任务的有效数据增强的基于单个图像的场景重新照明Single IMage-BAsed scene Relighting摘要真实世界的自动驾驶数据集由道路上不同驾驶的信息汇总而成。能够以可控的方式将捕捉到的场景重新照亮到不可见的照明条件&#xff0c;这提供了一个机…

SparkSQL-SparkOneHive

部署 连接Hive操作 小试牛刀&#xff1a;Hive版本的WordCount 从MySQL中读取数据存储到hive中 部署 1、Spark 要接管 Hive 需要把 hive-site.xml 拷贝到 conf/目录下 2、把 Mysql 的驱动 copy 到 jars/目录下 3、 如果访问不到 hdfs&#xff0c;则需要把 core-site.xml 和…

Beckhoff Ubuntu ADS库结构、编译与使用优化(像使用OpenCV一样使用ADS库!)

Beckhoff Ubuntu ADS库结构、编译与使用优化 库结构优化 倍福官方的ADS库结构看着不简洁&#xff0c;比较冗余&#xff0c;编译起来效果一般&#xff0c;而且不便于使用 官方ADS库原结构 redwallredwall-G3-3500:~/3rd_party/ADS$ tree . ├── AdsLib │ ├── AdsDef…

geometry:Jackson实现对JTS geometry对象的序列化和反序列化

在上一篇博文《geometry:MySQL的空间数据类型(Spatial Data Type)与JTS(OSGeo)类型之间的序列化和反序列化》中&#xff0c;实现了对MySQL数据库存储的WKB数据到JTS Geometry对象之间的转换。 当我们从数据库中得到的Geometry对象后&#xff0c;我们需要把它提供给前端时&#…

如何在工作日自动发送提醒?如何设置每3天提醒一次?

在日常工作中&#xff0c;经常会有一些在工作日的固定提醒&#xff0c;如在每个工作日提醒打卡。在现在市面上定时提醒相关功能基本都只能设置每天提醒或固定的如每周五&#xff0c;而腾讯云HiFlow中的定时启动&#xff0c;却逐渐在玩家们的呼喊声中逐渐智能。腾讯云HiFlow&…

寒冬期的春招之旅

1 Java基础 1.1 三大特性 封装、继承、多态 1.1.1 封装 1.1.2 继承 实例方法可直接调用啥&#xff1f; 实例方法可直接调用本类的类方法。 实例方法不可直接调用超类的实例方法。 实例方法不可直接调用超类的类方法 实例方法不可直接调用其他类的实例方法 note: 实例方…

【java】了解常见集合类

了解常见集合类 一、集合类框架 1、集合类框架结构图 首先我们要对集合类结构有一个大体的认识&#xff0c;所有集合都继承于迭代器&#xff0c;分为单列集合和映射集合&#xff0c;单列集合分为有序可重复和有序不可重复&#xff0c;大概结构如下图所示 2、主要集合类的介…