ISP—直方图拉伸

david 2022-02-07 09:00:14 3789

人生有很多的转折,每一个时段有每一个时段的颜色。

基于FPGA的直方图拉伸

1 背景知识

在视频处理中,为了能够实时调节图像的对比对,通常需要对直方图进行拉伸处理。直方图拉伸是指将图像灰度直方图较窄的灰度级区间向两端拉伸,增强整幅图像像素的灰度级对比度,达到增强图像的效果。

常用的直方图拉伸方法有线性拉伸、3段式分段线性拉伸和非线性拉伸等。FPGA中常见的是线性拉伸。

线性拉伸就是灰度拉伸,属于线性点运算的一种。它扩展图像的直方图,使其充满整个灰度级范围内。

设f(x,y) 为输入图像,它的最小灰度级A和最大灰度级B的定义如下:

A=min[f(x,y)];

B=max[f(x,y)];

将A和B分别映射到0和255,则最终的输出图像g(x,y)为

g(x,y)=255*[f(x,y)-A]/(B-A)

如上图所示,上a和下a分别为未进行拉伸的原始图像和直方图,上b和下b为拉伸后的图像和直方图。很容易发现直方图分布较窄的a图像经过拉伸后直方图变宽而且对比度明显提高。

2 matlab实现直方图拉伸

close all

clear all;

clc;

I = imread('car0.bmp');

Igray = rgb2gray(I);

Imin=min(min(Igray));

Imax=max(max(Igray));

HW = size(Igray);

H =HW(1);

W =HW(2);

C =255/(Imax-Imin);

Inew = zeros(size(Igray));

for i=1:H

for j=1:W

if(Igray(i,j)==Imin)

Inew(i,j)=0;

elseif(Igray(i,j)==Imax)

Inew(i,j)=255;

else

Inew(i,j)=(C.*(Igray(i,j)-Imin));

end

end

end

Inew = uint8(Inew);

figure(1),

subplot(221),imshow(Igray);

title('Igray');

subplot(223),imshow(Inew);

title('Inew');

subplot(222),imhist(Igray);

title('Igray');

subplot(224),imhist(Inew);

title('Inew');

Matlab实现彩色图像拉伸

<pre class="code-snippet__js" data-lang="makefile">```
<span class="code-snippet_outer">close all</span>

clear all;

<span class="code-snippet_outer">clc;</span>

<span class="code-snippet_outer">I = imread('lena.jpg');</span>

Istretch=HistRGB(I);

<span class="code-snippet_outer"> </span>

figure(1),

<span class="code-snippet_outer">subplot(211),imshow(I);</span>

title('I');

<span class="code-snippet_outer">subplot(212),imshow(Istretch);</span>

title('Istretch');

<pre class="code-snippet__js" data-lang="typescript">```
<span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">function</span> [<span class="code-snippet__title">OUT</span>] = <span class="code-snippet__title">HistRGB</span>(<span class="code-snippet__params">I</span>)</span></span>

for i = 1:3

<span class="code-snippet_outer"><span class="code-snippet_outer">        <span class="code-snippet__title">I</span>(<span class="code-snippet__params">:,:,i</span>) = <span class="code-snippet__title">HistGray</span>(<span class="code-snippet__params">I(:,:,i)</span>)</span>;</span>

end

<span class="code-snippet_outer">    OUT = uint8(I);</span>

end

<pre class="code-snippet__js" data-lang="makefile">```
<span class="code-snippet_outer">function [Inew] = HistStretch(Igray)</span>

Imin=min(min(Igray));

<span class="code-snippet_outer">Imax=max(max(Igray));</span>

<span class="code-snippet_outer">HW = size(Igray);</span>

H =HW(1);

<span class="code-snippet_outer">W =HW(2);</span>

C =255/(Imax-Imin);

<span class="code-snippet_outer">Inew = zeros(size(Igray));</span>

for i=1:H

<span class="code-snippet_outer">   for j=1:W</span>

if(Igray(i,j)==Imin)

<span class="code-snippet_outer">           Inew(i,j)=0;</span>

elseif(Igray(i,j)==Imax)

<span class="code-snippet_outer">           Inew(i,j)=255;</span>

else

<span class="code-snippet_outer">           Inew(i,j)=(C.*(Igray(i,j)-Imin));</span>

end

<span class="code-snippet_outer">   end</span>

end

<span class="code-snippet_outer">Inew = uint8(Inew);</span>

end

3 FPGA实现灰度图像拉伸

FPGA实现灰度图像的拉伸可分为真拉伸和伪拉伸,真拉伸需要对图像进行一帧的缓存,伪拉伸其实是在前一帧计算出最大和最后灰度级的基础上完成当前图像的拉伸处理,这样比较节省资源。

1,计算灰度图像的最大最小灰度级A,B;

2,完成灰度图像的拉伸。

<pre class="code-snippet__js" data-lang="properties">```
<span class="code-snippet_outer"><span class="code-snippet__attr">/**********************************</span></span>

copyright@FPGA OPEN SOURCE STUDIO

<span class="code-snippet_outer"><span class="code-snippet__attr">微信公众号:FPGA开源工作室</span></span>

***/

<span class="code-snippet_outer"><span class="code-snippet__meta">//800*600</span> =  <span class="code-snippet__string">480000</span></span>

//Pseudo histogram linear stretch

<span class="code-snippet_outer"><span class="code-snippet__meta">//Algorithm</span>:<span class="code-snippet__string">g(x,y) = 255*(f(x,y)-A)/(B-A)</span></span>

//B--Grayscale max

<span class="code-snippet_outer"><span class="code-snippet__meta">//A--Grayscale</span> <span class="code-snippet__string">min</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">module</span> <span class="code-snippet__string">hist_Stretch#(</span></span>

parameter DW = 24

<span class="code-snippet_outer">      <span class="code-snippet__attr">)(</span></span>

input pixelclk,

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span>                      <span class="code-snippet__string">reset_n,</span></span>

input [DW-1:0] din,//gray888

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span>                      <span class="code-snippet__string">i_hsync,</span></span>

input i_vsync,

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span>                      <span class="code-snippet__string">i_de,</span></span>

<span class="code-snippet_outer">  <span class="code-snippet__attr">output</span> <span class="code-snippet__string">[DW-1:0]dout,//gray out</span></span>

output o_hsync,

<span class="code-snippet_outer">      <span class="code-snippet__attr">output</span>                     <span class="code-snippet__string">o_vsync,</span></span>

output o_de

<span class="code-snippet_outer">   <span class="code-snippet__attr">);</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">wire</span> <span class="code-snippet__string">[7:0] gray = din[7:0];//gray--8bit</span></span>

reg [7:0] gray_r;

<span class="code-snippet_outer"><span class="code-snippet__attr">reg</span>        <span class="code-snippet__string">vsync_r;</span></span>

reg hsync_r;

<span class="code-snippet_outer"><span class="code-snippet__attr">reg</span>        <span class="code-snippet__string">de_r;</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">wire</span> <span class="code-snippet__string">[7:0]gray_max;//gray max</span></span>

wire [7:0]gray_min;//gray min

<span class="code-snippet_outer"> </span>

wire vsync_pos = (i_vsync&(!vsync_r));//frame start

<span class="code-snippet_outer"><span class="code-snippet__attr">wire</span>       <span class="code-snippet__string">vsync_neg = (!i_vsync&vsync_r);  //frame end</span></span>

assign dout = {gray_r,gray_r,gray_r};

<span class="code-snippet_outer"><span class="code-snippet__attr">assign</span> <span class="code-snippet__string">o_hsync = hsync_r;</span></span>

assign o_vsync = vsync_r;

<span class="code-snippet_outer"><span class="code-snippet__attr">assign</span> <span class="code-snippet__string">o_de = de_r;</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">always</span> <span class="code-snippet__string">@(posedge pixelclk) begin</span></span>

vsync_r

<span class="code-snippet_outer">  <span class="code-snippet__attr">hsync_r</span> <span class="code-snippet__string"></span></span>

de_r

<span class="code-snippet_outer"><span class="code-snippet__attr">end</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">always</span> <span class="code-snippet__string">@(posedge pixelclk or negedge reset_n)begin</span></span>

if(reset_n == 1'b0) begin

<span class="code-snippet_outer"><span class="code-snippet__meta">gray_r=<span class="code-snippet__string">0;</span></span></span>

end

<span class="code-snippet_outer">  <span class="code-snippet__attr">else</span> <span class="code-snippet__string">begin</span></span>

if(i_de ==1'b1) begin

<span class="code-snippet_outer">  <span class="code-snippet__attr">if(gray>gray_max)</span></span>

gray_r=8'd255;

<span class="code-snippet_outer">  <span class="code-snippet__attr">else</span> <span class="code-snippet__string">if(gray<gray_min></gray_min></span></span>

gray_r=8'd255;

<span class="code-snippet_outer">  <span class="code-snippet__attr">else</span></span>

//gray_r=255*(gray-gray_min)/(gray_max-gray_min);

<span class="code-snippet_outer"><span class="code-snippet__attr">gray_r</span> <span class="code-snippet__string"></span></span>

end

<span class="code-snippet_outer">  <span class="code-snippet__attr">end</span></span>

end

<span class="code-snippet_outer"> </span>

minmax#(.DW(8)

<span class="code-snippet_outer">      <span class="code-snippet__attr">)Uminmax(</span></span>

.pixelclk(pixelclk),

<span class="code-snippet_outer">      <span class="code-snippet__attr">.reset_n(reset_n),</span></span>

.din(gray),//gray--8

<span class="code-snippet_outer">      <span class="code-snippet__attr">.i_hsync(i_hsync),</span></span>

.i_vsync(i_vsync),

<span class="code-snippet_outer">      <span class="code-snippet__attr">.i_de(i_de),</span></span>

<span class="code-snippet_outer">  <span class="code-snippet__meta">.gray_max(gray_max),//gray</span> <span class="code-snippet__string">max out</span></span>

.gray_min(gray_min)//gray min out

<span class="code-snippet_outer">   <span class="code-snippet__meta">);</span>  <span class="code-snippet__string"></span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">function</span> <span class="code-snippet__string">[7:0] STRETCH;</span></span>

input [7:0] gray,gray_min,gray_max;

<span class="code-snippet_outer">  <span class="code-snippet__attr">begin</span></span>

STRETCH = 255*(gray-gray_min)/(gray_max-gray_min);

<span class="code-snippet_outer">  <span class="code-snippet__attr">end</span></span>

endfunction

<span class="code-snippet_outer">   </span>

endmodule

<pre class="code-snippet__js" data-lang="properties">```
<span class="code-snippet_outer"><span class="code-snippet__attr">/*</span></span>

Module name: minmax.v

<span class="code-snippet_outer"><span class="code-snippet__attr">Description</span>:  <span class="code-snippet__string">Get the maximum and minimum gray level of a frame of image</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">Date</span>:         <span class="code-snippet__string">2019/12/02</span></span>

微信公众号: FPGA开源工作室

<span class="code-snippet_outer"><span class="code-snippet__attr">*/</span></span>

`timescale 1ns/1ps

<span class="code-snippet_outer"><span class="code-snippet__attr">module</span> <span class="code-snippet__string">minmax#(parameter DW = 8</span></span>

)(

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span>                      <span class="code-snippet__string">pixelclk,</span></span>

input reset_n,

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span> <span class="code-snippet__string">[DW-1:0]    din,//gray--8</span></span>

input i_hsync,

<span class="code-snippet_outer">      <span class="code-snippet__attr">input</span>                      <span class="code-snippet__string">i_vsync,</span></span>

input i_de,

<span class="code-snippet_outer">  </span>

output reg [DW-1:0]gray_max,//gray max out

<span class="code-snippet_outer">  <span class="code-snippet__attr">output</span> <span class="code-snippet__string">reg  [DW-1:0]gray_min//gray min out</span></span>

);

<span class="code-snippet_outer"> </span>

reg [DW-1:0]gray_maxr;//gray max

<span class="code-snippet_outer"><span class="code-snippet__attr">reg</span> <span class="code-snippet__string">[DW-1:0]gray_minr;//gray min</span></span>

<span class="code-snippet_outer"><span class="code-snippet__meta">//reg</span>  <span class="code-snippet__string">[7:0] gray_r;</span></span>

reg vsync_r;

<span class="code-snippet_outer"><span class="code-snippet__attr">reg</span> <span class="code-snippet__string">de_r;</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">wire</span>       <span class="code-snippet__string">vsync_pos = (i_vsync&(!vsync_r));//frame start</span></span>

wire vsync_neg = (!i_vsync&vsync_r); //frame end

<span class="code-snippet_outer"> </span>

always @(posedge pixelclk) begin

<span class="code-snippet_outer">  <span class="code-snippet__attr">de_r</span> <span class="code-snippet__string"></span></span>

vsync_r=i_vsync;

<span class="code-snippet_outer"><span class="code-snippet__attr">end</span></span>

<span class="code-snippet_outer"><span class="code-snippet__attr">always</span> <span class="code-snippet__string">@(posedge pixelclk or negedge reset_n)begin</span></span>

if(!reset_n) begin

<span class="code-snippet_outer">    <span class="code-snippet__meta">gray_maxr= <span class="code-snippet__string">8'd0;</span></span></span>

gray_minr= 8'd255;

<span class="code-snippet_outer">  <span class="code-snippet__attr">end</span>  <span class="code-snippet__string"></span></span>

else begin

<span class="code-snippet_outer">    <span class="code-snippet__meta">if(i_vsync</span> =<span class="code-snippet__string">=1'b1 && i_de ==1'b1) begin</span></span>

gray_maxr= (gray_maxr>din)?gray_maxr:din;

<span class="code-snippet_outer">  <span class="code-snippet__meta">gray_minr= <span class="code-snippet__string">(din>gray_minr)?gray_minr:din;    </span></span></span>

end

<span class="code-snippet_outer"><span class="code-snippet__attr">else</span> <span class="code-snippet__string">if(vsync_neg == 1'b1)begin</span></span>

gray_max= gray_maxr;

<span class="code-snippet_outer">  <span class="code-snippet__meta">gray_min= <span class="code-snippet__string">gray_minr;</span></span></span>

gray_maxr= 8'd0;

<span class="code-snippet_outer">  <span class="code-snippet__meta">gray_minr= <span class="code-snippet__string">8'd255;</span></span></span>

end

<span class="code-snippet_outer"><span class="code-snippet__attr">else</span> <span class="code-snippet__string">begin</span></span>

gray_max= gray_max;

<span class="code-snippet_outer">  <span class="code-snippet__meta">gray_min= <span class="code-snippet__string">gray_min;</span></span></span>

gray_maxr= gray_maxr;

<span class="code-snippet_outer">  <span class="code-snippet__meta">gray_minr= <span class="code-snippet__string">gray_minr;</span></span></span>

end

<span class="code-snippet_outer">  <span class="code-snippet__attr">end</span></span>

end

<span class="code-snippet_outer"> </span>

<span class="code-snippet_outer"><span class="code-snippet__attr">endmodule</span></span>


![](https://ebaina.oss-cn-hangzhou.aliyuncs.com/wechat-official-crawl/2022-02/164419561389163.jpg)

![](https://ebaina.oss-cn-hangzhou.aliyuncs.com/wechat-official-crawl/2022-02/164419561395941.jpg)

未经拉伸的图像感觉蒙了一层雾,经过拉伸后图像对比度明显增强。

更懂精彩请扫码关注微信公众号

或公众号内查看往期文章

![](https://ebaina.oss-cn-hangzhou.aliyuncs.com/wechat-official-crawl/2022-02/164419561312526.jpg)

转载:全栈芯片工程师
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
david
红包 点赞 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
david
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区