精华内容
下载资源
问答
  • Matlab中的stretchlim函数详解
    2021-04-18 09:26:57

    Matlab中的stretchlim主要用于自适应找到一个分割阈值向量来改变一幅图像的对比度,其通用调用格式如下:

    low_high = stretchlim(f,tol);

    可得到一个灰度变换自适应最佳阈值,不用人为规定,再将其带入imadjust函数中便可实现灰度图像对比度的增加或减弱。

    g=imadjust(f,low_high,[ ]);%增强对比度代码示例

    一.

    若tol是一个含两元素的向量,设为[low_frac

    high_frac],假如我们想了解该函数如何得出的最佳灰度变换阈值,可选中该函数,右键open“stretchlim”。在此我就将结合Matlab的stretchlim函数源码分析其运算原理。

    1.tol_low = tol(1);

    2.tol_high = tol(2);

    3.ilowhigh = zeros(2,1);%创建一个2X1大小的矩阵,用于储存后文算出的特征值

    4.N=imhist(f,255);%计算输入图像f的灰度级数,即算出从1到255区间的任意一个灰度值i,在图像f中有多少个像素点的灰度值为i(uint8型共有255个灰度值,)

    5.cdf =cumsum(N)/sum(N);%计算1~255每个灰度值的分布概率,该灰度值处像素点

    的个数及灰度值小于该点的像素点个数之和与总像素点个数之比即为该灰度值的分布概率。例:A=[1 2

    3]  cumsum(A)=[13 6]

    6.ilow = find(cdf> tol_low,

    1,'first');%找到分布概率大于我们的输入值tol_low处最接近的灰度值,并以此作为最佳分割阈值的最小值

    7.ihigh = find(cdf

    >= tol_high, 1,'first');

    %找到分布概率大于或等于我们的输入值tol_high处最接近的灰度值,并以此作为最佳分割阈值的最大值

    8.if

    ilow ==

    ihigh%如果算出的最小值等于最大值的话,说明该输入图像为等灰度值图像

    9.ilowhigh

    = [1;255];%此时最佳分割阈值就为[0 1]

    10.else

    11.ilowhigh

    =[ilow;ihigh];

    12.end

    13.end

    14.low_high=

    (ilowhigh -

    1)/(255-1);% 由于在imadjust函数中的灰度分割阈值为0-1之间的实数,而我们在上面由分布概率得到的阈值是像素值形式,其值的范围为0-255。而之所以上下均-1,是因为阈值可以是[0

    1]而matlab的灰度级数去不能为0,最小为1

    注:输入图像f为​​uint8型的灰度图像,若对于自适应于其他格式的情况,理解上述程序后参考文章最后的源码。

    二.若tol是一个标量low_frac,那么上述程序的第1、2步则为

    tol_low = low_frac;

    tol_high = 1-low_frac;

    其余计算则与一情况完全相同

    三.若调用时忽略了参数tol,则上述程序的第1、2步为

    tol_low = 0.01;

    tol_high = 0.99;

    四.若tol=0;则直接得到输出阈值

    low_high=[min(f(:)),max(f(:))]

    五.自适应多种情况的源码:

    ​function lowhigh =

    The_note_of_stretchlim(varargin)

    %STRETCHLIM Find limits to

    contrast stretch an image.

    %

    LOW_HIGH = STRETCHLIM(I,TOL) returns a pair of gray values that can

    be

    %   used

    by IMADJUST to increase the contrast of an image.

    %

    %   TOL =

    [LOW_FRACT HIGH_FRACT] specifies the fraction of the image

    to

    %

    saturate at low and high pixel values.

    %

    %   If TOL

    is a scalar, TOL = LOW_FRACT, and HIGH_FRACT = 1 -

    LOW_FRACT,

    %   which

    saturates equal fractions at low and high pixel values.

    %

    %   If you

    omit the argument, TOL defaults to [0.01 0.99], saturating

    2%.

    %

    %   If TOL

    = 0, LOW_HIGH = [min(I(:)); max(I(:))].

    %

    %

    LOW_HIGH = STRETCHLIM(RGB,TOL) returns a 2-by-3 matrix of pixel

    value

    %   pairs

    to saturate each plane of the RGB image. TOL specifies the

    same

    %

    fractions of saturation for each plane.

    %

    %   Class

    Support

    %

    -------------

    %   The

    input image can be uint8, uint16, int16, double, or single, and

    must

    %   be

    real and nonsparse. The output limits are double and have

    values

    %

    between 0 and 1.

    %

    %

    Note

    %

    ----

    %   If TOL

    is too big, such that no pixels would be left after

    saturating

    %   low

    and high pixel values, then STRETCHLIM returns [0; 1].

    %

    %

    Example

    %

    -------

    %

    I =

    imread('pout.tif');

    %

    J =

    imadjust(I,stretchlim(I),[]);

    %

    figure, imshow(I), figure,

    imshow(J)

    %

    %   See

    also BRIGHTEN, DECORRSTRETCH, HISTEQ, IMADJUST.

    %

    Copyright 1999-2014 The MathWorks, Inc.

    [img,tol] = ParseInputs(varargin{:});

    if isa(img,'uint8')

    nbins =

    256;

    else

    nbins =

    65536;

    end

    tol_low = tol(1);%默认值的情况下tol = [0.01 0.99];

    �fault

    tol_high = tol(2);

    p = size(img,3);%size(img,1)为计算行数,size(img,2)为计算列数,3就是维数

    if tol_low < tol_high

    ilowhigh =

    zeros(2,p);%灰度图像维数为1

    for i = 1:p% Find limits, one plane at a

    time

    N = imhist(img(:,:,i),nbins);%计算灰度级数,即算出1~255,每个灰度级刻度对应有多少个像素为该灰度级

    cdf = cumsum(N)/sum(N); %cumulative distribution

    function(累积分布函数,就是概率论里面的分布函数)

    ilow = find(cdf > tol_low,

    1, 'first');

    ihigh = find(cdf >= tol_high,

    1, 'first');

    if ilow == ihigh

    % this could happen if img is

    flat当图像为单像素矩阵时概率分布为0.1和0.9是相等的

    ilowhigh(:,i) = [1;nbins];%这是输出的范围就是[0 1]了

    else

    ilowhigh(:,i) = [ilow;ihigh];%正常非单像素值矩阵时

    end

    end

    lowhigh = (ilowhigh

    - 1)/(nbins-1);% convert to range [0 1]将输出值归一化到[0

    1]

    else

    %   tol_low

    >= tol_high, this tolerance does not make sense. For

    example, if

    %   the tolerance is .5 then no

    pixels would be left after saturating

    %   low and high pixel values.

    In all of these cases, STRETCHLIM

    %   returns [0; 1]. See

    gecks(欺骗) 278249 and 235648.

    lowhigh =

    repmat([0;1],1,p);

    end

    %-----------------------------------------------------------------------------

    function [img,tol] = ParseInputs(varargin)

    narginchk(1, 2);

    img = varargin{1};

    validateattributes(img, {'uint8', 'uint16', 'double', 'int16',

    'single'}, {'real', ...

    'nonsparse','nonempty'},

    mfilename, 'I or

    RGB', 1);

    if (ndims(img) > 3)

    error(message('images:stretchlim:dimTooHigh'))

    end

    tol = [.01 .99]; �fault

    if nargin == 2

    tol =

    varargin{2};

    switch

    numel(tol)

    case 1

    tol(2) = 1

    - tol;

    case 2

    if (tol(1)

    >= tol(2))

    error(message('images:stretchlim:invalidTolOrder'))

    end

    otherwise

    error(message('images:stretchlim:invalidTolSize'))

    end

    end

    if ( any(tol < 0) || any(tol

    > 1) || any(isnan(tol)) )

    error(message('images:stretchlim:tolOutOfRange'))

    end

    更多相关内容
  • 接着来看一下stretchlim函数的原型 lowhigh = stretchlim(I) lowhigh = stretchlim(I,Tol) 对应到我们要实现的c++函数原型是这样的 std::vector strecthlim(cv::Mat img, double tol_low = 0.01, double tol_high =...

    灰阶变换

    首先介绍一下灰阶变换,一幅图像数据本身在存储的数据结构上为一个二维的矩阵,即一幅图像为m*n个密密麻麻的像素点构成。

    0d984223fa84

    image.png

    然后,这些像素点有着一个值,这个值成为灰度值或者亮度值,值的范围为[0,255],一共256级的亮度,也有成灰度级或灰阶的说法。那么如果把像素点的坐标(x, y)看作自变量,那么像素点的灰度值就可以看作它的函数值。

    0d984223fa84

    image.png

    然后灰阶变换就是函数值f(x,y)的变换了。就是一副像素点的灰度值按照某种规则或者关系从一个灰度级变换到另一个灰度级,变换的表达式如下。

    0d984223fa84

    image.png

    在matlab中,灰阶变换的两个工具函数,imadjust和stretchlim,接下来我们就用c++实现它。

    imadjust

    要实现imadjust函数,就先了解一下它,不知所以然就没法实现。这我们换看百度百科的介绍。

    imadjust是一个计算机函数,该函数用于调节灰度图像的亮度或彩色图像的颜色矩阵。在matlab的命令窗口中键入: doc imadjust或者help imadjust即可获得该函数的帮助信息, 键入type imadjust可以查看函数的源代码。

    再看看其函数原型

    J = imadjust(I)

    J = imadjust(I,[low_in; high_in],[low_out; high_out])

    J = imadjust(I,[low_in; high_in],[low_out; high_out],gamma)

    [newmap](https://baike.baidu.com/item/newmap) = imadjust(map,[low_in; high_in],[low_out;high_out],gamma)

    RGB2 = imadjust(RGB1,...)

    对应的要实现的c++函数原型是这样的

    void imadjust(cv::Mat& input, cv::Mat& output, double low_in = 0.0, double high_in = 1.0, double low_out = 0.0, double high_out = 1.0, double gamma = 1);//matlab,像素区间[0,1]

    void imadjust(cv::Mat& input, cv::Mat& output, std::vector in = { 0.0, 1.0 }, double low_out = 0.0, double high_out = 1.0, double gamma = 1);

    void imadjust2(cv::Mat& input, cv::Mat& output, int low_in, int high_in, int low_out, int high_out, double gamma = 1);//opencv,像素区间[0,255]

    接着是函数的功能

    该函数用于调节灰度图像的亮度或彩色图像的颜色矩阵

    来自官方帮助文档的使用示例

    I = imread('pout.tif');J = imadjust(I);imshow(I), figure, imshow(J)

    K = imadjust(I,[0.3 0.7],[]);figure, imshow(K)

    RGB1 = imread('football.jpg');RGB2 = imadjust(RGB1,[.2 .3 0; .6 .7 1],[]);

    imshow(RGB1), figure, imshow(RGB2)

    附上解释

    J = imadjust(I)

    将灰度图像 I 中的亮度值映射到 J 中的新值,使得图像中 1% 的数据饱和至最低和最高亮度,这可以增加输出图像 J 的对比度值。此用法相当于 imadjust(I,stretchlim(I))

    J = imadjust(I,[low_in; high_in],[low_out; high_out])

    将图像I中的亮度值映射到J中的新值,即将low_in至high_in之间的值映射到low_out至high_out之间的值。low_in 以下与 high_in 以上的值被剪切掉了,也就是说,low_in 以下的值映射到 low_out,high_in 以上的值映射到high_out。它们都可以使用空的矩阵[],默认值是[0 1]。

    J = imadjust(I,[low_in; high_in],[low_out; high_out],gamma)

    将图像 I 中的亮度值映射到 J 中的新值,其中 gamma指定描述值I和值J关系的曲线形状。如果gamma小于1,此映射偏重更高数值(明亮)输出,如果gamma大于1,此映射偏重更低数值(灰暗)输出,如果省略此参数,默认为(线性映射)。 《Simulink与信号处理》

    newmap = imadjust(map,[low_in; high_in],[low_out; high_out],gamma)

    调整索引色图像的调色板map。如果low_in, high_in, low_out, high_out 和 gamma 都是标量,那么对 r,g,b 分量同时都做此映射。对于每个颜色分量都有唯一的映射,当 low_in 和 high_in 同时为1*3向量或者 low_out 和 high_out 同时为1*3向量或者 gamma 为1*3向量时。调整后的颜色矩阵 [newmap](https://baike.baidu.com/item/newmap) 和 map 有相同的大小。

    RGB2 = imadjust(RGB1,...)

    对 RGB 图像 RGB1 的红、绿、蓝调色板分别进行调整。随着颜色矩阵的调整,每一个调色板都有唯一的映射值。

    这里我们着重理解一下行数原型的几个参数

    J = imadjust(I,[low_in; high_in],[low_out; high_out],gamma)

    I为输入的图像,函数的功能就是把输入图像在[low_in; high_in]灰度级中的像素点,映射为[low_out; high_out]区间的灰度级,gamma为一个可选参数,gamma = 1为线性变换,gamma != 1为伽马变换。

    0d984223fa84

    image.png

    0d984223fa84

    image.png

    0d984223fa84

    image.png

    下面来讲一下伽马变换。伽马变换又称幂次变换,变换公式为

    0d984223fa84

    gamma.gif

    0d984223fa84

    image.png

    好,下面开始代码的实现。

    先用一张表储存伽马变换的值,这样就不需要在每次变量像素点的时候都调用gamma变换公式计算

    std::vector gammaLut(const double gamma, const double c)

    {

    std::vector lut(256);

    for (int i = 0; i < 256; ++i)

    lut[i] = static_cast(c * std::pow((double)(i / 255.0), gamma) * 255.0);

    return lut;

    }

    然后遍历图像,对每个像素点进行灰阶变换操作

    for (int i = 0; i < rows; ++i)

    for (int j = 0; j < cols; ++j)

    {

    double result = 0;

    if (input.at(i, j) <= low_in)//灰度值小于low_in的像素点

    {

    result = low_out;//结果为low_out

    }

    else if (low_in < input.at(i, j) && input.at(i, j) < high_in)//灰度值在[low_in, high_in]

    {

    result = k * (input.at(i, j) - low_in) + high_in;//灰度值线性变换

    result = gamma_lut[static_cast(result)];//灰度值gamma变换

    }

    else

    {

    result = high_out;//灰度值大于high_in的像素点,结果为high_out

    }

    output.at(i, j) = static_cast(result) % 255;

    }

    下面放出完整代码

    //imadjust函数的实现

    #include

    #include

    #include

    #include

    void imadjust(cv::Mat& input, cv::Mat& output, double low_in = 0.0, double high_in = 1.0, double low_out = 0.0, double high_out = 1.0, double gamma = 1);//matlab,像素区间[0,1]

    void imadjust(cv::Mat& input, cv::Mat& output, std::vector in = { 0.0, 1.0 }, double low_out = 0.0, double high_out = 1.0, double gamma = 1);

    void imadjust2(cv::Mat& input, cv::Mat& output, int low_in, int high_in, int low_out, int high_out, double gamma = 1);//opencv,像素区间[0,255]

    std::vector gammaLut(const double gamma, const double c = 1.0);//灰度值的伽马变换结果表lut

    bool is0to1(const double var);

    int main()

    {

    cv::Mat src_img = cv::imread("Fig0304(a)(breast_digital_Xray).tif");

    if(src_img.empty()) return -1;

    cv::Mat dst_img;

    imadjust(src_img, dst_img, 0, 1, 0, 1, 2);

    cv::imshow("src_img", src_img);

    cv::imshow("dst_img", dst_img);

    cv::waitKey(0);

    return 0;

    }//main

    void imadjust(cv::Mat& input, cv::Mat& output, double low_in, double high_in, double low_out, double high_out, double gamma)

    {

    assert(low_in < high_in && is0to1(low_in) && is0to1(high_in) && is0to1(low_out) && is0to1(high_out));

    //将matlab中的灰度值区间[0,1]转为opencv灰度值区间[0,255]

    high_in *= 255; high_out *= 255; low_in *= 255; low_out *= 255;

    imadjust2(input, output, low_in, high_in, low_out, high_out, gamma);

    }

    void imadjust(cv::Mat& input, cv::Mat& output, std::vector in, double low_out, double high_out, double gamma)

    {

    assert(2 == in.size());

    double low_in = in[0];

    double high_in = in[1];

    imadjust(input, output, low_in, high_in, low_out, high_out, gamma);

    }

    void imadjust2(cv::Mat& input, cv::Mat& output, int low_in, int high_in, int low_out, int high_out, double gamma )//opencv,像素区间[0,255]

    {

    output = input.clone();

    int rows = input.rows;//行

    int cols = input.cols;//列

    double k = (static_cast(high_out) - low_out) / (high_in - low_in);

    std::vector gamma_lut = gammaLut(gamma);

    switch(input.channels())

    {

    case 1://灰度图

    for (int i = 0; i < rows; ++i)

    for (int j = 0; j < cols; ++j)

    {

    double result = 0;

    if (input.at(i, j) <= low_in)//灰度值小于low_in的像素点

    {

    result = low_out;//结果为low_out

    }

    else if (low_in < input.at(i, j) && input.at(i, j) < high_in)//灰度值在[low_in, high_in]

    {

    result = k * (input.at(i, j) - low_in) + high_in;//灰度值线性变换

    result = gamma_lut[static_cast(result)];//灰度值gamma变换

    }

    else

    {

    result = high_out;//灰度值大于high_in的像素点,结果为high_out

    }

    output.at(i, j) = static_cast(result) % 255;

    }

    break;

    //彩色图片

    case 3:

    for (int i = 0; i < rows; ++i)

    for (int j = 0; j < cols; ++j)

    for (int k = 0; k < 3; ++k)

    {

    double result = 0;

    if (input.at<:vec3b>(i, j)[k] <= low_in)

    result = low_out;

    else if (low_in < input.at<:vec3b>(i, j)[k] && input.at<:vec3b>(i, j)[k] < high_in)

    {

    result = k * (input.at<:vec3b>(i, j)[k] - low_in) + high_in;

    result = gamma_lut[static_cast(result)];

    }

    else

    {

    result = high_out;

    }

    output.at<:vec3b>(i, j)[k] = static_cast(result) % 255;

    }

    break;

    default:

    break;

    }

    }

    bool is0to1(const double var)

    {

    return 0 <= var && var <= 1;

    }

    std::vector gammaLut(const double gamma, const double c)

    {

    std::vector lut(256);

    for (int i = 0; i < 256; ++i)

    lut[i] = static_cast(c * std::pow((double)(i / 255.0), gamma) * 255.0);

    return lut;

    }

    测试效果

    0d984223fa84

    image.png

    stretchlim

    同样的,先看看这个函数有什么作用,stretchlim函数要用于自适应找到一个分割阈值向量来改变一幅图像的对比度。就是自动找到imadjust函数中[low_in; high_in]的合适值,所以说stretchlim是为imadjust函数服务的。

    接着来看一下stretchlim函数的原型

    lowhigh = stretchlim(I)

    lowhigh = stretchlim(I,Tol)

    对应到我们要实现的c++函数原型是这样的

    std::vector strecthlim(cv::Mat img, double tol_low = 0.01, double tol_high = 0.99);

    至于函数的实现原理和过程,看到这篇文章Matlab中的stretchlim函数详解,解释的非常清楚。我就不详细说明了,代码中也给了较多的注释。

    下面贴上代码

    头文件

    #pragma once

    #include

    #include

    #include

    std::vector calcGrayLevel(cv::Mat& img);//计算灰度级,即算出从0到255区间的任意一个灰度值i,在图像img中有多少个像素点的灰度值为i

    std::vector pdf(std::vector gray_level, cv::Mat& img);//计算概率密度pdf

    std::vector cdf(std::vector pdf);//计算概率分布cdf

    double findLow(double input_low, std::vector cdf);

    double findHihg(double input_high, std::vector cdf);

    std::vector strecthlim(cv::Mat img, double tol_low = 0.01, double tol_high = 0.99);

    cpp文件

    //2-2-1

    //stretchlim函数

    #include"stretchlim.h"

    #include

    int main()

    {

    cv::Mat img = cv::imread("./Fig0304(a)(breast_digital_Xray).tif", 0);

    if (img.empty()) return -1;

    std::vector v = strecthlim(img);

    for (auto& i : v)

    std::cout << i << std::endl;

    system("pause");

    return 0;

    }

    std::vector calcGrayLevel(cv::Mat& img)//计算灰度级,即算出从0到255区间的任意一个灰度值i,在图像img中有多少个像素点的灰度值为i

    {

    assert(img.channels() == 1);//只计算灰度图像的

    std::vector res(256);

    int rows = img.rows;//行

    int cols = img.cols;//列

    for(int i = 0; i < rows; ++i)

    for (int j = 0; j < cols; ++j)

    {

    int val = img.at(i, j);

    res[val] += 1;

    }

    return res;

    }

    std::vector pdf(std::vector gray_level, cv::Mat& img)//计算概率密度

    {

    assert(gray_level.size() == 256);

    int N = img.rows * img.cols;//像素点总数

    std::vector res(256);

    for (int i = 0; i < 256; ++i)

    res[i] =static_cast(gray_level[i]) / N;

    return res;

    }

    std::vector cdf(std::vector pdf)//计算概率分布cdf

    {

    assert(pdf.size() == 256);

    std::vector res(256);

    res[0] = pdf[0];

    for (int i = 1; i < 256; ++i)

    res[i] = pdf[i] + res[i - 1];

    return res;

    }

    double findLow(double input_low, std::vector cdf)

    {

    assert(cdf.size() == 256);

    //找到分布概率大于我们的输入值input_low处最接近的灰度值,并以此作为最佳分割阈值的最小值

    for (int i = 0; i < 256; ++i)

    if (cdf[i] > input_low)

    return cdf[i];

    return 0.0;

    }

    double findHihg(double input_high, std::vector cdf)

    {

    assert(256 == cdf.size());

    //找到分布概率大于或等于我们的输入值input_high处最接近的灰度值,并以此作为最佳分割阈值的最大值

    for(int i = 0; i < 256; ++i)

    if(cdf[i] >= input_high)

    return cdf[i];

    return 0.0;

    }

    std::vector strecthlim(cv::Mat img, double tol_low, double tol_high)

    {

    std::vector v(2);

    if (img.empty()) return v;

    //计算灰度值

    std::vector gray_level = calcGrayLevel(img);

    //计算概率密度pdf

    std::vector p = pdf(gray_level, img);

    //计算概率分布cdf

    std::vector c = cdf(p);

    //寻找tol_low, tol_high

    tol_low = findLow(tol_low, c);

    tol_high = findHihg(tol_high, c);

    if (tol_low == tol_high)

    v = { 0.0, 1.0 };

    else

    v = { tol_low, tol_high };

    return v;

    }

    展开全文
  • stretchlim函数

    千次阅读 2020-06-02 07:58:16
    low_high=stretchlim(f) low_high = 0 1 >> g2=imadjust(f,stretchlim(f),[]) >> imshow(g2) >> g3=imadjust(f,stretchlim(f),[1 0]) >>> imshow(g3) 可以看到这样增加了负片...

    在这里插入图片描述
    这幅图是正常显示。
    在这里插入图片描述

    >> low_high=stretchlim(f)
    
    low_high =
    
         0
         1
         >> g2=imadjust(f,stretchlim(f),[])
         >> imshow(g2)
    

    在这里插入图片描述

    >> g3=imadjust(f,stretchlim(f),[1 0])
    >>> imshow(g3)
    

    在这里插入图片描述
    可以看到这样增加了负片图像的对比度。
    stretchlim函数的语法:
    low_high=stretchlim(f,tol)
    tol-----两元素向量【low_frac high_frac】,指定了图像低和高像素值饱和度的百分比。

    展开全文
  • LOW_HIGH=stretchlim(img); J=imadjust(img,[LOW_HIGH(1) LOW_HIGH(2)],[0 1],1); imwrite(J,"/home/zhongjia/test_result.png"); 实现功能是:对16位深度1024*1024大小的test.png图像进行自适应灰度拉伸。 ...

    matlab 代码:
    [img,map]=imread(“/home/zhongjia/test.png”);
    LOW_HIGH=stretchlim(img);
    J=imadjust(img,[LOW_HIGH(1) LOW_HIGH(2)],[0 1],1);
     imwrite(J,"/home/zhongjia/test_result.png");  

    实现功能是:对16位深度1024*1024大小的test.png图像进行自适应灰度拉伸。

    stretchlim函数是寻找最合适的阈值,imadjust函数是进行灰度变换。

    python代码:

    (1)实现stretchlim函数

    matlab 的stretchlim函数默认是将累计像素点占整个像素点比例在0.01 ~0.99之间的像素值进行灰度变换,所以以下python代码仅仅实现stretchlim默认参数情况下的功能。

    计算每个像素值的像素点数量,绘制像素值直方图,找到某个阈值满足该阈值以下累计像素点数量占整个像素点(1024*1024)的比例低于0.01的像素值A1、A2、A3……,A1<A2<A3,同时找到某个像素阈值以上累计像素点占比低于0.01的像素值B1、B2、B3……,B1<B2<B3……。以A3和B1作为imadjust函数灰度变换时映射的端点

    import cv2 
    import numpy as np
    import scipy 
    from scipy import misc
    import matplotlib.pyplot as plt
     
    def calcGrayHist(I):
        # 计算灰度直方图
        h, w = I.shape[:2]
        #grayHist = np.zeros([256], np.uint64)
        grayHist = np.zeros([65536], np.uint64)
        for i in range(h):
            for j in range(w):
                grayHist[I[i][j]] += 1
        return grayHist
    img = cv2.imread('/home/zhongjia/plasmabubble/example_wk/plasma_bubble_20130929-30/20130929195902_gpi408_3_6300_180000_B1_G3.png.raw.png',2)
    plt.figure()
    plt.imshow(img,cmap='Greys_r')
    total_pixels = img.shape[0]*img.shape[1]
    print(total_pixels)
    grayHist = calcGrayHist(img)
    sum = np.zeros([65536],np.uint64)
    for i in range(65536):
        sum[i] = np.sum(grayHist[0:i+1])
    print(sum)
    cdf = np.zeros([65536],np.uint64)
    cdf = sum/total_pixels
    min_pix = np.where(cdf < 0.01)
    max_pix =  np.where(cdf >= 1 - 0.01)

    img_copy = img.copy()
    img_copy = np.rot90(img_copy,-1)# 顺时针旋转90度,np.rot90(img, -1) 顺时针旋转90度
    cv2.imwrite('pre_test.png',img_copy)

    plt.figure()
    plt.imshow(img_copy,cmap='Greys_r')

    结果:

    再实现imadjust函数:

    matlab imadjust函数如下:

    这个部分代码是将前面找到的阈值端点A3和B1输入到imadjust函数中,进行图像灰度拉伸。使得A3以下的像素值最后映射结果和A3映射结果相同,B1以上像素值映射结果和B1映射结果相同,从而将占比更大累计像素点的A3~B1像素值映射到新的像素空间。

    import cv2 
    import numpy as np
    import scipy 
    from scipy import misc
    import matplotlib.pyplot as plt
     

    def imadjust(img, low_in, high_in, low_out, high_out, gamma, c):
       
        #f = misc.imread(img).astype(np.int16)
        #f = misc.imread(img,2).astype(np.uint16)
        f = misc.imread(img,2)
        print(f.shape,f.dtype,f,f.max())
        plt.figure(1)
        plt.imshow(f, cmap='gray')
        plt.axis('off')
        plt.title('原始图像')
        plt.show()
        
        w, h = f.shape
        f1 = np.zeros([w, h])
        # imadjust函数运算部分
        for x in range(0, w):
            for y in range(0, h):
                if f[x, y] <= low_in:
                    f1[x, y] = low_out
                elif f[x, y] >= high_in:
                    f1[x, y] = high_out
                else:
                    f1[x, y] = c * (f[x, y]**gamma)
        f1 = np.rot90(f1,-1)# 顺时针旋转90度,np.rot90(img, -1) 顺时针旋转90度
        scipy.misc.imsave('figure2.png', f1)
        plt.figure(2)
        plt.imshow(f1, cmap='gray')
        plt.axis('off')
        plt.title('变换图像')
        plt.show()
        
        
        plt.figure(3)
        f2 = np.abs(f-f1)     #差值的绝对值
        
        scipy.misc.imsave('figure3.png', f2)
        plt.imshow(f2, cmap='gray')
        plt.axis('off')
        plt.title('差值图像')
        plt.show()
    imadjust('/home/zhongjia/plasmabubble/test.png', 740, 2218, 0, 255, 1, 1) 

    注意事项:

    本文是在stretchlim函数和imadjust函数中都保留图片uint16位深度,并没用直接通过imread函数读取时,先转换为uint8位深度,再进行stretch和imadjust函数变换。

    如果先通过imread函数默认读取,则自动将0-65535线性映射到0-255,如下测试代码:

    import cv2 as cv
    import numpy as np
    import matplotlib.pyplot as plt
    import math
    import os
    import glob
    import shutil
    import scipy 
    from scipy import misc
    img = cv.imread("/home/zhongjia/aurora/2005/alread_format/N20050101G_F/N050101G03508.png",0)
    print(img.dtype,img.min(),img.max(),img[300][200])
    # img = np.array(img,dtype='uint16')
    # print(img.dtype,img.min(),img.max(),img[60][200])
    # img = np.array(img,dtype='uint8')
    # print(img.dtype,img.min(),img.max(),img[60][200])
    img = cv.imread("/home/zhongjia/aurora/2005/alread_format/N20050101G_F/N050101G03508.png",2)
    print(img.dtype,img.min(),img.max(),img[300][200])

    输出结果:

    从保留两位小数看,确实imread函数读取uint16位图时(0~65535),若取深度uint8,则压缩到0~255

    压缩了像素值空间,有可能导致如下问题:原来像素空间里面,累积像素点占比0.01的阈值端点精确阈值是A3和B1,在新的像素空间里面,累计像素点占比0.01的点不是精确的两个阈值点,因为像素空间分辨率降低了,从65536到256,每个像素值对应的点变多了。所以原来A3阈值映射到新空间是0,B1映射到255,而现在可能是C3映射到新空间的0,D1映射到255。

    我们看一下先转换uint8时,再进行后续操作的结果:

    展开全文
  • 灰度变换函数:imadjust和stretchlim

    千次阅读 2019-05-19 04:20:14
    二、函数 `stretchlim(f)` 一、函数 imadjust 和函数 imcomplement 函数imadjust是对灰度图像进行亮度变换的函数 语法: g = imadjust(f,[low_in high_in],[low_out high_out],gamma) 函数 imadjust 中各种...
  • 2、stretchlim函数 在imadjust函数选择灰度区间时,也可使用stretchlim自适应选择。 low_high=stretchlim(f,tol),生成的是一个1*2的向量 而后应用imadjust函数 g=imadjust(f,low_high,[]); 其中tol是一个1*2的向量...
  • % 负片显示的另一种方法 【stretchlim 对比度拉伸】stretch伸展 limit限制 不想关心imadjust 的参数 [low_in high_in],[low_out high_out],偷了个懒,使用: low_high=stretchlim(f) %对比度拉伸,是一个两元素的...
  • 通常利用stretchlim配合imadjust来自动地提高图片的对比度,而不关心参数高低的处理。  因为在利用c++实现stretchlim时用到了imhist,因此这里再说说imhist,matlab原型 h = imhist(f, b) 1 imhist用于处理...
  • matlab的stretchlim函数

    千次阅读 2017-10-22 11:29:24
    function lowhigh = stretchlim(varargin) %STRETCHLIM Find limits to contrast stretch an image. % LOW_HIGH = STRETCHLIM(I,TOL) returns a pair of intensities that can be % used by IMADJUST to increas
  • void stretchlim(Mat &srcImage, Mat& lowHigh, vector<double> tol = vector<double> {0.01, 0.99}) { int nbins = 256; double tol_low, tol_high; double low, high; lowHigh.create (2, srcImage.channels ...
  • 灰度变换--imadjust和stretchlim

    千次阅读 2017-06-01 21:44:47
    % 自动的使用函数imadjust,不必关心参数大小问题时,使用函数stretchlim % Low_High = stretchlim(f,tol) % Low_High是一个两元素向量,由一个低限和一个高限组成,小于这个低限的值的像素占整张图片的tol,大于这...
  • stretchlim可以生成一个二元素向量,该向量有一个低限和一个高限组成。LOW_HIGH = stretchlim(f) MATLAB: function f = Image_Negatives() f = imread('Fig0203(a).tif'); imshow(f); %负片...
  • matlab中的imadjust函数的第一种调用方式为:imadjust(I), I为待处理图像,在参数封装时调用了stretchlim函数。但opencv中没有相应的实现,故参照matlab的源代码实现了stretchlim函数。该函数用了上一篇文章中实现的...
  • 在这个例子中,我们写两种MATLAB版本的函数,创建一幅以下面等式为基础的合成图像。 第一个函数twodsin1使用两个嵌套的for循环计算f: function f=twodsin1(A,u0,v0,M,N) f=zeros(M,N); for c=1:N ...
  • 灰度变换: g = imadjust(f, [low_in high_in], [low_out ...g5 = imadjust(f, stretchlim(f), [1 0]); figure, imshow(g5); f:   g1: = 255-f   g2:    g3:      
  • matlab开发-查找主要峰值和谷值动物直方图。此函数用于查找图像直方图的主峰和局部谷值。

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 353
精华内容 141
关键字:

stretchlim