FPGA图像处理之rgbtogray算法的实现

FPGA图像处理之rgbtogray算法的实现

作者:lee神

1.背景知识

在正是入题之前先给大家讲解一下gray图像,YUV图像以及Ycbcr图像。

Gray图像:灰度图像就是我们常说的黑白图像,由黑到白为灰阶为0-255。

YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间。在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取得的彩色图像信号经分色、分别放大校正后得到RGB,再经过矩阵变换电路得到亮度信号Y和两个色差信号B-Y(即U)、R-Y(即V),最后发送端将亮度和色差三个信号分别进行编码,用同一信道发送出去。这种色彩的表示方法就是所谓的YUV色彩空间表示。采用YUV色彩空间的重要性是它的亮度信号Y和色度信号U、V是分离的。YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过RGB输入信号来建立的,方法是将RGB信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面─色调与饱和度,分别用Cr和Cb来表示。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。

Ycbcrr或Y'CbCr有的时候会被写作:YCBCR或是Y'CBCR,是色彩空间的一种,通常会用于影片中的影像连续处理,或是数字摄影系统中。Y'为颜色的亮度(luma)成分、而CB和CR则为蓝色和红色的浓度偏移量成份。Y'和Y是不同的,而Y就是所谓的流明(luminance),表示光的浓度且为非线性,使用伽马修正(gamma correction)编码处理。

2.FPGA实现RGB图像转Gray图像方法

一般RGB像转灰度(gray)图像有两种方法,第一种就是使用RGB图像的单通道去显示图像(R,G或B)。

其二就是讲RGB图像转换成Ycbcr图像,使用Y分量去显示图像,来实现彩色图像转灰度图。

3.RGB单通道实现灰度图像的转换

上图为整个图像显示的架构。我们采用RGB565格式。

RGB单通道实现灰度图像FPGA源码:

//----------------------------------------------------------------------

// R G B to gray

//----------------------------------------------------------------------

wire[15:0] rgb;

assignTFT_rgb = ; //red

//assignTFT_rgb = ; //green

//assignTFT_rgb = ; //blue

//assignTFT_rgb = ; //blue

实现结果

原图

Red分量

Green分量

Blue分量

由上三个分量显示图像来看,Green分量显示效果较好。大家可以多试其他图像,这种方法比较简单,容易实现。

4 RGB图像转Ycbcr图像实现gray图像。

RGB转Ycbcr算法:

计算公式:Y = 0.183R + 0.614G + 0.062B + 16;

CB = -0.101R -0.338G + 0.439B + 128;

CR = 0.439R - 0.399G - 0.040B + 128;

其中,时序在计算过程中完全没有用到

输入到输出有三个clock的时延。

第一级流水线计算所有乘法;

第二级流水线计算所有加法,把正的和负的分开进行加法;

第三级流水线计算最终的和,若为负数取;

Modelsim仿真部分希望自己去做。

RGB转Ycbcr FPGA源码:

/*

RGB转YUV算法

计算公式:Y = 0.183R + 0.614G + 0.062B + 16;

CB= -0.101R - 0.338G + 0.439B + 128;

CR= 0.439R - 0.399G - 0.040B + 128;

其中,时序在计算过程中完全没有用到

输入到输出有三个clock的时延。

第一级流水线计算所有乘法;

第二级流水线计算所有加法,把正的和负的分开进行加法;

第三级流水线计算最终的和,若为负数取;

仿真通过

*/

`timescale1ns/1ps

module rgb_to_ycbcr(

input clk,

input [7 : 0] i_r_8b,

input [7 : 0] i_g_8b,

input [7 : 0] i_b_8b,

input i_h_sync,

input i_v_sync,

input i_data_en,

output [7 : 0] o_y_8b,

output [7 : 0] o_cb_8b,

output [7 : 0] o_cr_8b,

output o_h_sync,

output o_v_sync,

output o_data_en

);

/***************************************parameters*******************************************/

//multiply256

parameter para_0183_10b = 10'd47; //0.183定点数

parameter para_0614_10b = 10'd157;

parameter para_0062_10b = 10'd16;

parameter para_0101_10b = 10'd26;

parameter para_0338_10b = 10'd86;

parameter para_0439_10b = 10'd112;

parameter para_0399_10b = 10'd102;

parameter para_0040_10b = 10'd10;

parameter para_16_18b = 18'd4096;

parameter para_128_18b = 18'd32768;

/********************************************************************************************/

/***************************************signals**********************************************/

wire sign_cb;

wire sign_cr;

reg[17:0] mult_r_for_y_18b;

reg[17:0] mult_r_for_cb_18b;

reg[17:0] mult_r_for_cr_18b;

reg[17:0] mult_g_for_y_18b;

reg[17:0] mult_g_for_cb_18b;

reg[17:0] mult_g_for_cr_18b;

reg[17:0] mult_b_for_y_18b;

reg[17:0] mult_b_for_cb_18b;

reg[17:0] mult_b_for_cr_18b;

reg[17:0] add_y_0_18b;

reg[17:0] add_cb_0_18b;

reg[17:0] add_cr_0_18b;

reg[17:0] add_y_1_18b;

reg[17:0] add_cb_1_18b;

reg[17:0] add_cr_1_18b;

reg[17:0] result_y_18b;

reg[17:0] result_cb_18b;

reg[17:0] result_cr_18b;

reg[9:0]y_tmp;

reg[9:0]cb_tmp;

reg[9:0]cr_tmp;

reg i_h_sync_delay_1;

reg i_v_sync_delay_1;

reg i_data_en_delay_1;

reg i_h_sync_delay_2;

reg i_v_sync_delay_2;

reg i_data_en_delay_2;

reg i_h_sync_delay_3;

reg i_v_sync_delay_3;

reg i_data_en_delay_3;

/********************************************************************************************/

/***************************************initial**********************************************/

initial

begin

mult_r_for_y_18b

mult_r_for_cb_18b

mult_r_for_cr_18b

mult_g_for_y_18b

mult_g_for_cb_18b

mult_g_for_cr_18b

mult_b_for_y_18b

mult_g_for_cb_18b

mult_b_for_cr_18b

add_y_0_18b

add_cb_0_18b

add_cr_0_18b

add_y_1_18b

add_cb_1_18b

add_cr_1_18b

result_y_18b

result_cb_18b

result_cr_18b

i_h_sync_delay_1

i_v_sync_delay_1

i_data_en_delay_1

i_h_sync_delay_2

i_v_sync_delay_2

i_data_en_delay_2

end

/********************************************************************************************/

/***************************************arithmetic*******************************************/

//LV1pipeline : mult

always @(posedge clk)

begin

mult_r_for_y_18b

mult_r_for_cb_18b

mult_r_for_cr_18b

end

always @(posedge clk)

begin

mult_g_for_y_18b

mult_g_for_cb_18b

mult_g_for_cr_18b

end

always @(posedge clk)

begin

mult_b_for_y_18b

mult_b_for_cb_18b

mult_b_for_cr_18b

end

//LV2pipeline : add

always @(posedge clk)

begin

add_y_0_18b

add_y_1_18b

add_cb_0_18b

add_cb_1_18b

add_cr_0_18b

add_cr_1_18b

end

//LV3pipeline : y + cb + cr

assign sign_cb = (add_cb_0_18b >=add_cb_1_18b);

assign sign_cr = (add_cr_0_18b >=add_cr_1_18b);

always @(posedge clk)

begin

result_y_18b

result_cb_18b

result_cr_18b

end

always @(posedge clk)

begin

y_tmp

cb_tmp

cr_tmp

end

//output

assign o_y_8b =(y_tmp[9:8] == 2'b00) ? y_tmp[7 : 0] : 8'hFF;

assign o_cb_8b =(cb_tmp[9:8] == 2'b00) ? cb_tmp[7 : 0] : 8'hFF;

assign o_cr_8b =(cr_tmp[9:8] == 2'b00) ? cr_tmp[7 : 0] : 8'hFF;

/********************************************************************************************/

/***************************************timing***********************************************/

always @(posedge clk)

begin

i_h_sync_delay_1

i_v_sync_delay_1

i_data_en_delay_1

i_h_sync_delay_2

i_v_sync_delay_2

i_data_en_delay_2

i_h_sync_delay_3

i_v_sync_delay_3

i_data_en_delay_3

end

//--------------------------------------

//timing

//--------------------------------------

assign o_h_sync = i_h_sync_delay_3;

assign o_v_sync = i_v_sync_delay_3;

assign o_data_en = i_data_en_delay_3;

/********************************************************************************************/

Endmodule

代码2:

////////////////////////////////////////////////////////////////

wire[15:0] rgb;

wire hs;

wire vs;

wire de;

wire[7 :0] o_y_8b;

wire[7 :0] o_cb_8b;

wire[7 :0] o_cr_8b;

assignTFT_rgb = ; //Y

//assignTFT_rgb = ; //cb

//assignTFT_rgb = ; //cr

代码已经过验证,实现效果

原图

Y分量实现效果

此方法实现RGB转gray图像效果较好。

5引用文档

YUV--------------------------------------------------------百度百科

Ycbcr-------------------------------------------------------百度百科

本文来自企鹅号 - 全球大搜罗媒体

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI研习社

教你从零开始检测皮卡丘-CNN目标检测入门教程(下)

本文为大家介绍实验过程中训练、测试过程及结果。算法和数据集参见《从零开始码一个皮卡丘检测器-CNN目标检测入门教程(上)》 训练 Train 损失函数 Lo...

33830
来自专栏MelonTeam专栏

机器学习入门系列05,classification: probabilistic generative model(分类:概率生成模型)

引用课程:http://speech.ee.ntu.edu.tw/~tlkagk/courses_ml16.html 先看这里,可能由于你正在查看这个平台行...

45150
来自专栏专知

【干货】计算机视觉实战系列08——用Python做图像处理

27220
来自专栏机器之心

教程 | 详解如何使用Keras实现Wassertein GAN

选自Deeply Random 机器之心编译 参与:晏奇、李泽南 在阅读论文 Wassertein GAN 时,作者发现理解它最好的办法就是用代码来实现其内容。...

529100
来自专栏计算机视觉战队

CVPR 2018 笔记

知乎号:https://www.zhihu.com/people/chang-you-li-92/activities

9910
来自专栏大数据文摘

手把手 | OpenAI开发可拓展元学习算法Reptile,能快速学习(附代码)

16230
来自专栏进击的程序猿

如何生成一幅艺术作品

假设我们有一幅大师的画作了,我们怎么能够提取出“大师作品”中的纹理和颜色这些细节让我们的计算机知道,而不是只看到画的整体造型呢?

14330
来自专栏Deep learning进阶路

深度学习论文(八)---DeepLabV1-SEMANTIC IMAGE SEGMENTATION WITH DEEP CONVOLUTIONAL NETS AND FULLY CONNECTED C

注:本篇算是半讲解半翻译吧,我真的觉得这篇论文写的很难理解.......可能是我水平不够,也可能作者省略了一些具体信息,主要是提供了他的idea吧。 但是De...

1.1K10
来自专栏杂七杂八

机器学习分类

机器学习通常分为四类 监督学习 无监督学习 半监督学习 强化学习 监督学习 监督学习是从标记的训练数据来推断一个功能的机器学习任务。在监督学习中,每个实例都是由...

37860
来自专栏自学笔记

The Optimization of the Adaboost and Gradient Boosted Decision Tree

再回到我们上篇文章讲到的Adaboost算法,我们要从Adaboost算法推导出GBDT。首先回顾一下上篇文章的Adaboost,主要思想就是把弱分类器集中起来...

10920

扫码关注云+社区

领取腾讯云代金券