【数字图像处理】RGB 转灰度图

news/2024/7/21 7:33:43 标签: fpga开发, 图像处理, 紫光同创

常见的数字图像格式有 RGB, RGBA, YCbCr 等,RGB/RGBA 格式适合存储,而 YCbCr 格式适合图像处理。在数字图像处理中,通常需要将 RGB 格式的图像变换为灰度图,再进行后续的处理,例如边缘检测、锐化等。本文主要介绍数字图像 RGB 转灰度图的基本原理,并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。

目录

1. RGB 转灰度图原理

2. FPGA 布署与实现

2.1 功能与指标定义

2.2 模块设计

2.3 上板调试


1. RGB 转灰度图原理

        在研究生物视觉的过程中,人们发现人眼视网膜中包含三种视锥细胞,这三种视锥细胞的光谱吸收峰值不同,对应光的波长分别处于 450 nm, 530nm 和 570 nm 附近,对应光的颜色分别为蓝、绿、红。

        考虑人眼对不同颜色光的感知程度不同,对红、绿、蓝 3 个颜色分量分别设定一个权重,颜色分量值与对应权重相乘再累加,就得到灰度值。

        目前关于颜色权重的选取,仍存在一些争议,但总的偏差不大。常用的 RGB 转灰度图的公式如下:

Gray = 0.299 \times R + 0.587 \times G + 0.114 \times B

使用 Matlab 进行验证。

clc, clear

% 读取图像
im = imread('./loopy.png');
im = im2double(im);

% RGB转灰度图
im_r = im(:,:,1);
im_g = im(:,:,2);
im_b = im(:,:,3);
im_new = 0.299*im_r +0.587*im_g +0.114*im_b;

% 查看图像
subplot(121)
imshow(im)
title('原图像')
subplot(122)
imshow(im_new)
title('处理后图像')

2. FPGA 布署与实现

2.1 功能与指标定义

        使用紫光同创 FPGA 平台实现 RGB 转灰度图功能,FPGA 需要实现的功能与指标如下:

(1)与电脑的串口通信,用于接收用户下发的图像,波特率为 256000 Bd/s;

(2)RGB 转灰度图处理,使用 FPGA 内部的乘法器,实现颜色分量的加权;

(3)DDR3 读写控制,将处理前后的图像数据分别写入 DDR3 的不同区域,实现图像的拼接;

(4)HDMI 输出,输出一路 HDMI 信号源,用于将拼接后的图像显示在外接显示器上,分辨率为 1024×768。

2.2 模块设计

        主要的设计模块功能划分如下:


top_uart 模块

· uart_rx_slice 模块,UART 串口接收驱动模块

· uart_rx_parse 模块,UART 串口数据解析模块,从上位机接收 RGB 8bit 图像

top_vidin 模块

· vidin_pipeline 模块,缓存两行图像(使用乒乓操作),并将数据提交到 ddr3 用户数据调度模块

· mult_9x9_uaub IP,乘法器 IP,输入为 2 个 9bit 无符号数,输出为 18bit 无符号数

merge_out 模块

· dvi_timing_gen 模块,根据定义的分辨率,产生 HDMI 视频控制时序

· dvi_ddr_rd 模块,根据 HDMI 控制信号,提交读指令到 ddr3 用户数据调度模块

· dvi_encoder 模块,HDMI 输出编码(8b10b 编码)与输出驱动

· dvi_pll IP,PLL IP,将参考时钟倍频,产生需要的像素时钟信号

其中,乘法器的输入为 2 个 9bit 无符号数,RGB 颜色分量为 8bit,颜色分量系数需要扩大 512 倍再取整,由

0.299 \times 512 = 153.088 

0.587 \times 512 = 300.544

0.114 \times 512 = 58.368

得 RGB 乘法器相乘系数分别取:153,301 和 58。

FPGA 工程资源使用率如下:

4925a8030c3d4f7b814f139460e721f2.png

2.3 上板调试

使用 PyQt5 和 OpenCV 库,编写上位机程序,实现以下功能:

(1)使用 OpenCV 库加载图像,并截取左上角 512 × 384 的区域;

(2)通过串口发送给 PGL22G 开发板。

# -*- Coding: UTF-8 -*-
import cv2
import sys
import struct
from PyQt5 import Qt, QtGui, QtCore, QtWidgets, QtSerialPort

class mainWindow(Qt.QWidget):
   def __init__(self, com_port, parent=None):
      super(mainWindow, self).__init__(parent)
      #self.setGeometry(720, 300, 512, 384)
      self.setFixedSize(530, 384)
      self.setWindowTitle("PGL OpenCV Tool")

      # 创建标签与按钮
      self.img_widget = QtWidgets.QLabel()
      self.btn1 = QtWidgets.QPushButton("打开")
      self.btn1.clicked.connect(self.getfile)
      self.btn2 = QtWidgets.QPushButton("关闭")
      self.btn2.clicked.connect(self.close)

      # 创建布局
      centralLayout = QtWidgets.QVBoxLayout()
      centralLayout.addWidget(self.img_widget)
      bottomLayout = QtWidgets.QHBoxLayout()
      bottomLayout.addWidget(self.btn1)
      bottomLayout.addWidget(self.btn2)
      centralLayout.addLayout(bottomLayout)
      self.setLayout(centralLayout)

      # 串口对象
      self.COM = QtSerialPort.QSerialPort()
      self.COM.setPortName(com_port)
      self.COM.setBaudRate(256000)
      self.open_status = False
      self.row_cnt = 0
      self.img = None
      self.timer = QtCore.QTimer()
      self.timer.timeout.connect(self.sendImage)
      self.startup()

   def startup(self):
      """Write code here to run once"""
      for com_port in QtSerialPort.QSerialPortInfo.availablePorts():
         print(com_port.portName())

      # Try open serial port
      if not self.COM.open(QtSerialPort.QSerialPort.ReadWrite):
         self.open_status = False
         print("Open Serial Port failed.")
      else:
         self.open_status = True

   def getfile(self):
      """获取图像路径"""
      fname = QtWidgets.QFileDialog.getOpenFileName(self, 'Open file',
         'C:\\Users\\Administrator\\Pictures', "Image files(*.jpg *.png)")
      self.clipImage(fname[0])
      self.updateImage()
      self.sendImage()

   def clipImage(self, fname):
      """读取并裁剪图片至512x384大小"""
      if fname:
         img = cv2.imread(fname, cv2.IMREAD_COLOR)
         img_roi = img[:384,:512,:]
         print(img_roi.shape)
         cv2.imwrite('./img_roi.png', img_roi)

   def updateImage(self):
      """显示裁剪后的图像"""
      self.img_widget.setPixmap(QtGui.QPixmap('./temp/img_roi.png'))
      self.img = cv2.imread('./img_roi.png')
      self.timer.start(100)

   def sendImage(self):
      """通过串口发送图片"""
      pattern = ">4H{:d}B".format(512*3)

      if self.open_status:
         if self.row_cnt == 384:
            self.row_cnt = 0
            self.timer.stop()
         else:
            args1 = [self.row_cnt, self.img.shape[0], 0, 0]
            args2 = [rgb for rgb in self.img[self.row_cnt,:].reshape(-1)]
            send_data = struct.pack(pattern, *(args1+args2))
            self.row_cnt += 1
            self.COM.write(send_data)

def main():
   app = QtWidgets.QApplication(sys.argv)
   window = mainWindow('COM21')
   window.show()
   sys.exit(app.exec_())

if __name__ == "__main__":
   main()

 297055f22e75458a83586a9a3a6e2d98.png

        在电脑端发送图像,就可以看到 FPGA 处理结果了 ~


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

相关文章

2023.11.13-istio之故障注入流量拆分流量镜像熔断-oss

istio之故障注入&流量拆分&流量镜像&熔断 目录 文章目录 istio之故障注入&流量拆分&流量镜像&熔断目录本节实战1、故障注入注入 HTTP 延迟故障🚩 实战:注入 HTTP 延迟故障-2023.11.12(测试成功) 注入 HTTP abort 故障&#x1f6…

Linux输入与输出设备的管理

计算机系统中CPU 并不直接和设备打交道,它们中间有一个叫作设备控制器(Device Control Unit)的组件,例如硬盘有磁盘控制器、USB 有 USB 控制器、显示器有视频控制器等。这些控制器就像代理商一样,它们知道如何应对硬盘…

汽车ECU的虚拟化技术初探(二)

目录 1.概述 2.U2A虚拟化方案概述 3.U2A的虚拟化功能概述 4.虚拟化辅助功能的使能 5.留坑 1.概述 在汽车ECU的虚拟化技术初探(一)-CSDN博客里,我们聊到虚拟化技术比较关键的就是vECU的虚拟地址翻译问题,例如Cortex-A77就使用MMU来进行虚实地址的转换…

每天一道算法题:47. 全排列 II

难度 中等 题目 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 示例 1: 输入:nums [1,1,2] 输出: [[1,1,2], [1,2,1], [2,1,1]] 示例 2: 输入:nums [1,2,3] 输出:[[1,2,3],[1,3,2…

sass 封装媒体查询工具

背景 以往写媒体查询可能是这样的&#xff1a; .header {display: flex;width: 100%; }media (width > 320px) and (width < 480px) {.header {height: 50px;} }media (width > 480px) and (width < 768px) {.header {height: 60px;} }media (width > 768px) …

openssl+sha256开发实例(C++)

文章目录 一、 sha256介绍二、sha256原理三、openssl sha256实现 一、 sha256介绍 SHA-256&#xff08;Secure Hash Algorithm 256-bit&#xff09;是一种哈希算法&#xff0c;属于 SHA-2&#xff08;Secure Hash Algorithm 2&#xff09;家族的一员。SHA-256 产生的哈希值是一…

100天精通Python(可视化篇)——第107天:Pyecharts绘制多种炫酷旭日图参数说明+代码实战

文章目录 专栏导读一、旭日图介绍1. 旭日图是什么?2. 旭日图的应用场景?3. 旭日图和饼图的区别?二、参数说明1. 导包2. add函数三、旭日图实战1. 普通旭日图2. 家庭关系旭日图3. 四川省旭日图4. 烟酒茶旭日图5. 官方示例书籍推荐专栏导读 🔥🔥本文已收录于《100天精通P…

QMessageBox详解

文章目录 基本用法详解QMessageBox 是 Qt 框架中用于显示消息框(弹窗)的类。它用于在应用程序中向用户显示信息、提供选择等交互操作。下面是 QMessageBox 的一些常见用法和详解: 基本用法 #include <QMessageBox>// 显示一个简单的信息框 QMessageBox::information…