图像压缩(1)RGB888与RGB565图像

news2024/11/15 12:00:31

图像压缩(1)RGB888与RGB565图像

  • 前言
  • 一. 图像数据格式
    • 1.1 不同RGB格式
      • (1)RGB16
      • (2)RGB24
      • (3)RGB32
      • (4)ARGB32
    • 1.2 RGB565与RGB888对比
      • (1)区别
      • (2)各自优缺点
  • 二. 图像格式转换
    • 2.1 取位与补位
    • 2.2 其他转换方法
  • 三. 图像压缩
    • 3.1 G6压缩法(16位真彩色数据压缩算法)
    • 3.2 基于FPGA片上ROM的RGB565屏幕图像显示
  • 四. RGB888和RGB565颜色对照表

前言

   最近在接触图像压缩相关项目,之前对图像压缩接触的较少,对检测分类识别相关的图像信号处理接触学习的相对比较多一些,所以也需要学习学习,搜集整理了一些资料,在这里简单做个笔记,也分享出来和大家交流学习。

一. 图像数据格式

   RGB色彩模式是工业界的一种颜色标准,是通过对红、绿、蓝三原色进行组合得到各种各样不同颜色的表示,这在初中物理就有的,RGB三个通道颜色的组合,几乎囊括了人类视力所能感知的所有颜色,因此成为目前运用最广的颜色系统之一。一般而言,我们所感知的现实视觉与各类硬件平台的图像视觉是有很大差距的,不同现实设备因其设备资源限制与具体应用需求,并不需要高精度的显示需求,在满足清晰可见的基础上,可能对传输或存储的要求更严苛。由此产生各种类型的RGB格式:如RGB16、RGB24、RGB32、ARGB32等等。

1.1 不同RGB格式

(1)RGB16

RGB16数据格式主要有二种:RGB565(或者是R5G6B5)和RGB555(或者是R5G5B5)。
RGB565:每个像素用16比特位表示,占2个字节,RGB分量分别使用5位、6位、5位。
RGB555:每个像素用16比特位表示,占2个字节,RGB分量都使用5位(最高位空闲)。

(2)RGB24

一般RGB24即指RGB888(或者是R8G8B8)
RGB888:每个像素用24比特位表示,占3个字节,注意:在内存中RGB各分量的排列顺序为:BGR BGR BGR 

(3)RGB32

RGB32:图像每个像素用32比特位表示,占4个字节,R,G,B分量分别用8个bit表示,存储顺序为B,G,R,最后8个字节保留。注意:在内存中RGB各分量的排列顺序为:BGRA BGRA BGRA 。

(4)ARGB32

就是带alpha通道的RGB24,与RGB32的区别在于,保留的8个bit用来表示透明,也就是alpha的值
ARGB8888:每个像素用24比特位表示,占3个字节,注意:在内存中ARGB各分量的排列顺序为:BGRA BGRA BGRA 

1.2 RGB565与RGB888对比

(1)区别

正常的RGB24是由24位即3个字节来描述一个像素,R、G、B各8位。而实际使用中为了减少图像数据的尺寸,如视频领域,对R、G、B所使用的位数进行的缩减,如RGB565和RGB555。

RGB565 就是R-5bit,G-6bit,B-5bit
RGB555 就是R-5bit,G-5bit,B-5bit
RGB888 就是R-8bit,G-8bit,B-8bit ;其实这就是RGB24

RGB565,16bit
RGB888,24bit

另外常见的BMP图像文件,即是在RGB的像素数据基础上增加位图头数据而成的图像文件格式。

一般BMP是BGR888,jpeg是YUV的,其他的要看各自格式的标准描述。

(2)各自优缺点

从屏幕自身说,屏幕自身的控制器必须要达到RGB888的标准,才可以使用RGB888,相比RGB565,需要屏幕主控的存储空间增加1/2。RGB888的颜色分辨率肯定要比565高,造价成本更高。RGB565一方面可以降低成本,同时,减少单片机传输的数据量,能够实现2^16种颜色,满足一般的使用场景;主要缺点,就是色域没有RGB888广。

二. 图像格式转换

在这里学习一下RGB888与RGB565的转换,即24位色彩与16位色彩的转换:

2.1 取位与补位

24位RGB[23:0]转16位RGB[15:0]是通过取高位来实现的。取RGB[23:19],RGB[15:10],RGB[7:3]作为RGB三原色的值。
16位RGB[23:0]转24位RGB[15:0]是通过补位来实现的。使用位拼接的语法为RGB低位补0至8位即可。

2.2 其他转换方法

R8 = ( R5 * 527 + 23 ) >> 6;
G8 = ( G6 * 259 + 33 ) >> 6;
B8 = ( B5 * 527 + 23 ) >> 6;

R5 = ( R8 * 249 + 1014 ) >> 11;
G6 = ( G8 * 253 +  505 ) >> 10;
B5 = ( B8 * 249 + 1014 ) >> 11;

Apple ( iOS Accelerate Framework ):
Pixel8 red = (5bitRedChannel * 255 + 15) / 31 
Pixel8 green = (6bitGreenChannel * 255 + 31) / 63 
Pixel8 blue = (5bitBlueChannel * 255 + 15) / 31

三. 图像压缩

3.1 G6压缩法(16位真彩色数据压缩算法)

此方法并非是我们常见的PNG,JPG的压缩算,此方法只是应用于单片机刷新RGB565图片,压缩和解压过程不需要很大的运算量,对单片机比较友好。但是压缩率也比较低;可以知道图像数据存在多处的相等,这是因为图片的颜色基本没变。很多图像都是有这样的特征:存在颜色的连续。那么我们可以利用颜色的连续特征来压缩数据的存储空间,如果颜色相同,我们就只保留一个数据,这样就节省了2Byte的存储空间。

G6位用来存储一个标志,这个标志的含义:如果相邻两个像素点相等,这个标志位被置1,否则置0。这样我们不需要开辟数据去存储标志了。算法分析:比如第一个点的数据是2,第二个点的数据也是2,那么算法就把第一个点的G6位置1,同时直接隐藏第二个数据。接着我们看第三个数据,虽然第三个数据和第二个数据相同,但是此处不能再隐藏了,因为上个数据就进行了隐藏。第三个数据保留,第四个数据就进行了隐藏。第五个数据保留,因为第六个数据和第五个数据不同,所以第五个数据的G6位置0,后续同理。

压缩前的数据为2,2,2,2,2,3,4,2

压缩后的数据为2(G6=1),2(G6=1),2,3,4,2

解压时,第一个数据为2,我们先判断G6位,这里被置1了,所以这个数据2出现2次,然后下一个2是同样的道理。第三个2,因为G6位没有置1,所以只有1个。

压缩率计算:假设一个图片宽度W,高度H,数据格式RGB565,那么存储这个图片需要的空间为W×H×2 Byte。

如果采用上述压缩算法进行压缩,那么最大的压缩情况是,1,2相等,3,4相等,等等等。此时压缩后的数据量为W×H Byte。如果全图无重复的地方,那就没有压缩,不会出现负压缩的情况。所以此方法的压缩率为50%< G6压缩法 <100% (边界情况暂不考虑是否相等)。总结:此方法是将RGB565的 G6位用来存储标志,进行相邻数据相等压缩,实际的编程中,还会在压缩数据的头位置加上压缩后的数据长度,压缩前的数据长度,压缩前的图片规格等信息。

void YS1_G6(unsigned char PIC[])
{
	int i;//循环变量
	int PIC_Addr;//运行到输入图像的位置,不可到达
	//PIC_SAVE[0]=;长度高位
	//PIC_SAVE[1]=;长度低位
	//第一步,遍历原来的数据
	PIC_SAVE[2]=PIC[0];//第一个数据
	PIC_SAVE[3]=PIC[1];//第二个数据
	//PIC_SAVE[3]&=~0X20;
	//PIC_SAVE[4]=;//存储循环长度
	PIC_Addr=4;//不可到达位置,长度
	i=0;
	while(i<16383)//两个一组进行分组,循环16382次
	{
		i++;
		//后边和前边一样,将第六位置1
		if((PIC_SAVE[PIC_Addr-2]==PIC[i*2])&&(PIC_SAVE[PIC_Addr-1]==PIC[i*2+1]))
		{
			PIC_SAVE[PIC_Addr-1]|=0X20;
			i++;
		}
		else//写入当前数据,并将第六位置零
		{
			PIC_SAVE[PIC_Addr-1]&=~0X20;
		}
		if(i<16384)//防止存储非法数据
		{
			//每次处理后必定写入一个数据
			PIC_SAVE[PIC_Addr]=PIC[i*2];//第一个数据
			PIC_SAVE[PIC_Addr+1]=PIC[i*2+1];//第二个数据
			//PIC_SAVE[PIC_Addr+1]&=~0X10;
			PIC_Addr+=2;//到达下个存储长度位置
		}

		//i++;//每次循环后必定处理数据,i向后移动
	}
	PIC_SAVE[0]=PIC_Addr/256;//长度高位
	PIC_SAVE[1]=PIC_Addr%256;//长度低位
	printf("压缩后的长度为%d",PIC_Addr);
} 

算法说明:压缩后的数据前两位保存的是压缩后的数据长度,这个很重要,是解压时循环次数的依据。还有算法中的循环次数和边界问题,暂时不展开分析。此算法不是通用算法,后续会加入图片的长度计算(输入数据包含数据信息),同时生成的压缩后数据也会存在数据头,这样的算法会比较通用,不至于出现因为压缩对象的更改,而需要手动修改数据。 这里只简单分析一下流程。

第一步:首先我们需要查询并创建一个C文件(txt文件也可以用)。

第二步:然后我们处理一下输入的数据,清除G6位。

第三步:进行压缩,然后计算出压缩后的长度。

第四步:将压缩后的数据保存,然后传输,即可完成压缩编码部分。

G6压缩方法确实有压缩效果,但是效果并不是那么明显,没有达到最好的效果,这是因为图像数据不可能完全相邻相等。获得压缩后的数据时,就可以进行“G6压缩法”的解压。

解压的过程,是压缩的逆过程,此压缩算法的解压是要比压缩过程简单,计算比较少。

解压的算法:最多是计算一下压缩后的数据长度,然后一直循环解压,这里我们先送给屏幕一个数据,如果G6位为1,我们再刷新一次,否则就接着向下循环。每次循环都会后移动两位(因为RGB565是2Byte,数组一般是8位) ,使用G6压缩法,压缩和解压都是比较简单的操作,不涉及大量的计算,压缩过程有大量的数据相等判断操作,解压过程是大量的与运算判断操作。算法可以实现数据的压缩,但是压缩率不是很高。

3.2 基于FPGA片上ROM的RGB565屏幕图像显示

为了实现16位彩色图像的显示,需要对图片压缩(片上ROM的限制)。示例采用60*100像素的图片(总计72000bits),即显示的时候需要将图像放大8倍显示(480×800)。同样使用Img2Lcd软件图片转为需要的bmp格式(水平扫描模式、16位真彩色)(或者用PS、截图(保存为bmp格式)、电脑自带画图软件等,都可以完成转换)。之后使用Matlab将bmp文件信息转化为RGB565格式的mif文件,m文件的源码如下。

clear;
clc;
n=6000;%100*60--16bit
myImg = imread('example.bmp');%读取.bmp文件
fid=fopen('example.mif','w');%打开待写入的.mif文件
fprintf(fid,'WIDTH=16;\n');%写入存储位宽16fprintf(fid,'DEPTH=6000;\n');%写入存储深度6000
fprintf(fid,'ADDRESS_RADIX=UNS;\n');%写入地址类型为无符号整型
fprintf(fid,'DATA_RADIX=HEX;');%写入数据类型为16进制
fprintf(fid,'CONTENT BEGIN\n');%起始内容
image(myImg);
for i=0:n-1         %RGB888 -> RGB565
    x = mod(i,100)+1;
    y = fix(i/100)+1;
    r = uint16(myImg(y,x,1)/8);
    g = uint16(myImg(y,x,2)/4);
    b = uint16(myImg(y,x,3)/8);%由于输出的图像为uint8,所以等式左边的变量无法赋值为其他类型
    r = dec2bin(r);
    g = dec2bin(g);
    b = dec2bin(b);%十进制转二进制
    r = num2str(r);
    g = num2str(g);
    b = num2str(b);%数字转字符串
    
    if length(r)==1 %根据字符串长度补零--r
        r = strcat('0000',r);
    elseif length(r)==2
        r = strcat('000',r);
    elseif length(r)==3
        r = strcat('00',r);
    elseif length(r)==4
        r = strcat('0',r); 
    else
        r = r;
    end
    if length(g)==1 %根据字符串长度补零--g
        g = strcat('00000',g);
    elseif length(g)==2
        g = strcat('0000',g);
    elseif length(g)==3
        g = strcat('000',g);
    elseif length(g)==4
        g = strcat('00',g); 
    elseif length(g)==5
        g = strcat('0',g);
    else
        g = g;
    end    
    if length(b)==1 %根据字符串长度补零--b
        b = strcat('0000',b);
    elseif length(b)==2
        b = strcat('000',b);
    elseif length(b)==3
        b = strcat('00',b);
    elseif length(b)==4
        b = strcat('0',b); 
    else
        b = b;
    end    
        
    k = strcat(r,g,b);
    %k = str2num(k);
    k = bin2dec(k);
    fprintf(fid,'\t%d:%x;\n',i,k);
    %disp(k);
end
fprintf(fid,'END;\n');
fclose(fid);%关闭文件

查阅Matlab中文手册得知,软件读取8位的bmp图像时转化为单个矩阵。而读取16位bmp图像时,将其转化为3个8位矩阵,所以提取图像数据转为RGB565时需要除以特定的数。因为Matlab会把数据自动转化为uint8类型,所以需要将数据强制类型转换为二进制。在数据的高位补零后,再用字符串连接函数,将其连接为16位的字符串。最后用二进制转十进制函数,把字符串直接转为数字,存与指定的mif文件中。定制好ROM为16位,6000深度,例化下载后,其显示结果如下(其实,由于matlab读取16位bmp图像时,将其转化为3个8位矩阵。故可不需要用软件转换为16位的bmp文件再用matlab提取数据)。显示的Verilog主要程序如下:

/*color_rom--彩色-16位*/        
    localparam
        BMP_W            =    11'd100,   //显示区域宽度 = 图片宽
        BMP_H            =    11'd60;   //显示区域高度 = 图片高
    
    wire [12:0]  pic_addr;    
    wire [15:0] q;
    assign pic_addr = hcount[10:3] + vcount[10:3]*BMP_W;
    
    color16_rom color16_rom(
        .address(pic_addr),
        .clock(clk),
        .q(q)
    );
    assign disp_data = q;
/*color_rom-end*/

在计算机中,图像以RGB888显示,24位图每个像素保存了32bit的数据,即RGB888+Alpha,但是对于真彩色图像而言,肉眼在16bit的时候已经难以分辨了,因此,有些时候,可以将RGB888转换为RGB565来存储,减少存储器容量的同时,降低了数据量;在后端显示时,再次把RGB565转换为RGB888,就实现数据宽度的匹配!

RGB888->RGB565->RGB888

但是,RGB888->RGB565时,自然只要提取高位即可,但会导致低位的缺失;同时,但当RGB565->RGB888时,势必导致低位的缺失。为了数据的饱和以及色彩的减小,提出了一种新的思维,新的算法:量化补偿

(1)RGB888-RGB565

24bit RGB888 -> 16bit RGB565 的转换
24ibt RGB888 {R7 R6 R5 R4 R3 R2 R1 R0} {G7 G6 G5 G4 G3 G2 G1 G0} {B7 B6 B5 B4 B3 B2 B1 B0}
16bit RGB565 {R7 R6 R5 R4 R3} {G7 G6 G5 G4 G3 G2} {B7 B6 B5 B4 B3}
可以修正,比如(当然人眼无法感觉,但是RG888-RGB565-RGB888的时候更好补偿)
R:197=>197>>3=24
R:197=192+5=>24+0.625≈25
所以
R5=R[2] ? R[7:3]+1 : R[7:3];
G5=G[1] ? G[7:2]+1 : G[7:2];
B5=B[2] ? B[7:3]+1 : B[7:3];

(2)RGB565-RGB888
16bit RGB565 -> 24bit RGB888 的转换
16bit RGB656 {R4 R3 R2 R1 R0} {G5 G4 G3 G2 G1 G0} {B4 B3 B2 B1 B0}
24ibt RGB888 {R4 R3 R2 R1 R0 0 0 0} {G5 G4 G3 G2 G1 G0 0 0} {B4 B3 B2 B1 B0 0 0 0}
24ibt RGB888 {R4 R3 R2 R1 R0 R2 R1 R0} {G5 G4 G3 G2 G1 G0 G1 G0} {B4 B3 B2 B1 B0 B2 B1 B0}

因此,量化压缩的方法:RGB取高位,并且考虑最低位“四舍五入”,量化补偿的方法:

  1. 将原数据填充至高位
  2. 对于低位,用原始数据的低位进行补偿

四. RGB888和RGB565颜色对照表

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1126033.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最新2023版完美可用的聚合支付系统源码,全开源无后门,适合二开

最新2023版完美可用的聚合易支付系统源码&#xff0c;全开源无后门&#xff0c;真正安全可用。 更新日志&#xff1a; 1.新增微信公众号消息提醒功能 2.重构转账付款功能&#xff0c;支持通过插件扩展 3.商户后台新增代付功能 4.后台新增付款记录列表 5.支付宝插件新增预…

城市公安可视化大数据展示平台预测预警,防患未然

在当今数字化、信息化的时代背景下&#xff0c;数字化浪潮席卷着全国各地公安系统&#xff0c;以数字孪生为底座的智慧公安数字孪生可视化管控平台已经成为公共安全领域的一大发展趋势&#xff0c;以其独特的优势为公安机关的日常管理和警务指挥带来了革命性的变革。 智慧公安解…

【FPGA】IIC协议通用主机接口的设计与实现详解

一、认识IIC IIC&#xff08;I2C&#xff09;协议是一种串行通信协议&#xff0c;用于连接微控制器和外围设备。IIC协议只需要两根信号线&#xff08;时钟线SCL和数据线SDA&#xff09;就能完成设备之间的通信&#xff1b;支持多主机和多从机通信&#xff0c;通过设备地址区分不…

cmd命令快速打开MATLAB

文章目录 复制快捷方式添加 -nojvm打开 复制快捷方式 添加 -nojvm 打开 唯一的缺点是无法使用plot&#xff0c;这一点比不上linux系统&#xff0c;不过打开速度还是挺快的。

模式识别——贝叶斯决策理论

模式识别——贝叶斯决策理论BDR 须知基本原则0-1损失下的BDRMAP&#xff08;极大后验&#xff09;log trick 须知 所有内容在分类问题下讨论。 基本原则 定义 X X X为观测 Y Y Y为状态 g ( x ) g(x) g(x)用 x x x对 y y y进行预测预测损失为 L [ g ( x ) , i ] L[g(x),i] L[…

LVS---负载均衡

集群&#xff1a;为解决某个特定问题将多个计算机组合起来形成一个单系统 提高性能的两个方向 垂直扩展&#xff1a;向上扩展&#xff0c;增加单个机器的性能。升级硬件。硬件升级是由瓶颈的水平扩展:向外扩展&#xff0c;增加设备。并行的运行多个服务,通过网络和算法&…

Linux系统编程(4)

分配数组 int *x, *y; x malloc(50*sizeof(int)); if(!x) {perror("malloc");return 1; }y calloc(50, sizeof(int)); if (!y) {perror("calloc");return 1; } calloc会将所申请的内存全部填充0&#xff0c;malloc则不会。 调整内存分配的大小 #incl…

驱动开发4 使用字符设备驱动的分步实现编写LED驱动(LED亮灯)

一、思维导图 二、通过字符设备驱动的分步实现编写LED驱动&#xff0c;另外实现特备文件和设备的绑定 应用程序 test.c #include<stdlib.h> #include<stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include…

嵌入式linux系统中设备树基础知识

笔记整理自百问网正点原子 前言 之前分享的笔记&#xff1a;【Linux笔记】总线设备驱动模型中在platform_device部分有简单说明描述设备有两种方法&#xff1a;一种是使用platform_device结构体来指定&#xff1b;另一种是使用设备树来描述。 本篇笔记我们就来简单地学习一下…

系列三、其他流

一、缓冲流 1.1、概述 缓冲流也叫高效流&#xff0c;是对最基本的FileInputStream、FileOutputStream、FileReader、FileWriter的增强&#xff0c;所以也是4个流&#xff0c;按照数据类型分为如下种类 字节缓冲流&#xff1a;BufferedInputStream、BufferedOutputStream字符…

一、C++入门

1 C关键字 C语言中有32个关键字&#xff0c;而在C中有63个关键字。 当前我们不对关键字进行具体了解&#xff0c;等后续要用到的时候再学习该如何使用。 2 命名空间 在C和C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称将都…

pr加马赛克怎么加?

PR是常用的视频剪辑和处理软件&#xff0c;能够对视频进行一些美化、编辑处理等&#xff0c;大家都知道视频处理一个比较常见的操作那就是添加马赛克。那么&#xff0c;pr加马赛克能不能操作呢&#xff1f;其实是很简单的处理方式&#xff0c;下边&#xff0c;我们就一起看看如…

Redis实战之年会抽奖

前言&#x1f50d; 上一篇&#xff1a;Redis实战之微博点赞 本篇涉及相关命令&#xff1a;Sadd、Spop 示例基于SpringBoot 2.7.14 Sadd Sadd 命令将一个或多个成员元素加入到集合中&#xff0c;已经存在于集合的成员元素将被忽略。假如集合 key 不存在&#xff0c;则创建一…

小程序 this.setData is not a function解决办法

报错是因为函数中有 wx.showModal 或者 wx.request等请求&#xff0c;放在请求体里面时会报错。 this组用域的问题&#xff0c;success函数包实际上是一个闭包&#xff0c;无法通过this来直接setData 怎样修改呢&#xff1f; 我们需要将当&#xff0c;前对象赋予给一个新的对…

Flappy bird项目

一、功能分析 1、小鸟自动向右滑行 2、按下空格小鸟上升&#xff0c;不按下落 3、显示小鸟需要穿过的管道 4、管道自动左移和创建 5、小鸟和管道碰撞&#xff0c;游戏结束 6、技术 7、 项目框图 8、Ncurses 1&#xff09;创建窗口界面&#xff0c;移动光标&#xff0c;产…

Linux系统CH347应用—I2C功能

Linux/安卓系统使用CH347转接I2C功能有三种应用方式&#xff1a; 1. 使用CH34X_MPHSI_Master总线驱动为系统扩展原生I2C Master&#xff0c;此方式无需进行单独的应用层编程&#xff1b; 2. 使用CH341PAR_LINUX字符设备驱动&#xff0c;此方式需要配合使用厂商提供的库文件&a…

数据要素安全流通:挑战与解决方案

文章目录 数据要素安全流通&#xff1a;挑战与解决方案一、引言二、数据要素安全流通的挑战数据泄露风险数据隐私保护数据跨境流动监管 三、解决方案加强数据安全防护措施实施数据隐私保护技术建立合规的数据跨境流动机制 四、数据安全流通的未来趋势01 数据价值与产业崛起02 多…

CUDA学习笔记(十四) Constant Memory

转载至https://www.cnblogs.com/1024incn/tag/CUDA/ CONSTANT MEMORY constant Memory对于device来说只读但是对于host是可读可写。constant Memory和global Memory一样都位于DRAM&#xff0c;并且有一个独立的on-chip cache&#xff0c;比直接从constant Memory读取要快得多…

iPhone开发--Xcode15下载iOS 17.0.1 Simulator Runtime失败解决方案

爆句粗口&#xff0c;升级后公司网络下载iOS 17.0.1 Simulator Runtime一直出错&#xff0c;每次出错后都得重新开始下载&#xff0c;oh&#xff0c;f**k。上一次在在家里的网络升级成功。 解决办法一&#xff1a; 进入网址&#xff1a;https://developer.apple.com/download…

【产品设计】B端SaaS产品原则

B端产品设计并不是一个人的事情&#xff0c;往往是一个团队共同完成的。在整个团队中&#xff0c;会涉及到四个环节&#xff1a;需求环节、设计环节、研发环节和运营环节。在这些环节中&#xff0c;需要遵循一些原则&#xff0c;共同推动整个产品建设。 本文针对产品的需求环节…