RTT(RT-Thread)线程间同步(保姆级)

目录

线程间同步

信号量

信号量结构体

信号量的使用和管理

动态创建信号量

实例

静态创建信号量

初始化和脱离信号量

获取信号量

信号量的互斥操作

获取信号量函数

释放信号量

信号量同步实例

互斥量(互斥锁)

互斥量的使用和管理

动态创建互斥量

动态创建过程

静态创建互斥量

静态创建过程

获取互斥量

释放互斥量

互斥锁实例

事件集

动态创建事件集

创建和删除

静态创建事件集

初始化和脱离

事件集创建过程

事件集实现线程同步

发送事件

接收事件

实现原理

实现过程

事件集实现进程同步源码


 

线程间同步

        多个执行单元(线程、中断)同时执行临界区(多个执行单元会同时执行到的代码区域),操作临界资源,会导致竟态产生,为了解决这种竟态问题,RT-Thread OS提供了如下几种同步互斥机制:

  • 信号量
  • 互斥量
  • 事件集

同步的概念是:多个执行单元执行临界区的时候按照顺序的方式执行

互斥的概念:互斥强调的是排他性,比如有两个线程A和B。当线程A执行的时候,线程B不能执行;线程B执行的时候,线程A不能执行。只有当一个线程执行完之后,另一个线程才能执行。

信号量

        信号量是一种轻型的用于解决线程间同步问题的内核对象,线程可以获取或释放它,从而达到同步互斥的目的。

        每个信号量对象都有一个信号量值和一个线程等待队列,信号量的值对应了信号量对象的实例数目、资源数目,假如信号量值为 5,则表示共有 5 个信号量实例(资源)可以被使用,当信号量实例数目为零时,再申请该信号量的线程就会被挂起在该信号量的等待队列上,等待可用的信号量实例(资源)。

信号量结构体

当信号量被使用,value的值减1;当信号量被释放,value值加1

struct rt_semaphore
{struct rt_ipc_object parent; /**< inherit from ipc_object  继承自ipc_object类*/rt_uint16_t          value;       /**< value of semaphore. */rt_uint16_t         reserved;    /**< reservedfield 预留*/ 
};typedef struct
rt_semaphore *rt_sem_t;

信号量的使用和管理

        对一个信号量的操作包含:创建 /初始化信号量、获取信号量、释放信号量、删除 / 脱离信号量。

        创建完信号量之后,需要找到临界区,在临界区之前获取信号量,在临界区之后要释放信号量。

动态创建信号量

参数1:信号量名字

参数2:信号量资源个数

参数3:#define RT_IPC_FLAG_FIFO 0x00 //按照线程先进先出获取信号量资源

             #define RT_IPC_FLAG_PRIO 0x01 //按照线程优先级获取信号量资源

返回值为信号量结构体指针

/*** This function will create a semaphore from system resource** @param name the name of semaphore* @param value the initial value of semaphore* @param flag the flag of semaphore** @return the created semaphore, RT_NULL on error happen** @see rt_sem_init*/
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)

系统不再使用信号量时,可通过删除信号量以释放系统资源,适用于动态创建的信号量。

调用这个函数时,系统将删除这个信号量。如果删除该信号量时,有线程正在等待该信号量,那么删除操作会先唤醒等待在该信号量上的线程(等待线程的返回值是-RT_ERROR),然后再释放信号量的内存资源。

/*** This function will delete a semaphore objectand release the memory** @param sem the semaphore object** @return the error code** @see rt_sem_detach*/
rt_err_t rt_sem_delete(rt_sem_t sem)
实例

semaphore为信号量的名字,V为信号量的当前资源数,suspend thread为挂载在信号量上的线程数。但发现信号量名字少了最后面的“1”

注意名字设置的时候,必须要小于等于8个字符

静态创建信号量

初始化和脱离信号量
/*** This function will initialize a semaphoreand put it under control of* resource management.** @param sem the semaphore object* @param name the name of semaphore* @param value the initial value of semaphore* @param flag the flag of semaphore** @return the operation status, RT_EOK onsuccessful*/
rt_err_t rt_sem_init(rt_sem_t    sem,const char *name,rt_uint32_t value,rt_uint8_t  flag)

脱离信号量就是让信号量对象从内核对象管理器中脱离,适用于静态初始化的信号量,

使用该函数后,内核先唤醒所有挂在该信号量等待队列上的线程,然后将该信号量从内核对象管理器中脱离。原来挂起在信号量上的等待线程将获得 - RT_ERROR 的返回值。

/*** This function will detach a semaphore from resource management** @param sem the semaphore object** @return the operation status, RT_EOK on successful** @see rt_sem_delete*/
rt_err_t rt_sem_detach(rt_sem_t sem)

 

 

获取信号量

        线程通过获取信号量来获得信号量资源实例,当信号量值大于零时,线程将获得信号量,并且相应的信号量值会减 1,如果信号量的值等于零,那么说明当前信号量资源实例不可用,申请该信号量的线程将根据time参数的情况选择直接返回、或挂起等待一段时间、或永久等待,直到其他线程或中断释放该信号量。如果在参数time指定的时间内依然得不到信号量,线程将超时返回,返回值是 - RT_ETIMEOUT。

        比如说现在有线程1和线程2两个线程同时都能执行临界区的代码,在临界区存在一个临界资源变量i。此时线程1和线程2是存在竞态关系的,我们可以通过信号量来阻止竞态的发生。

        我们将信号量的value设置为1,在进入临界区之前,我们先获取信号量,在出临界区的时候再释放信号量。那么不管是线程1还是线程2,谁先执行临界区,都会先获取信号量,然后信号量value减1,变成0;此时线程2发现信号量value为0,就会选择休眠。直到线程1释放掉信号量,value值加1,就会唤醒线程2。那么线程2就会获取到信号量,从而操作临界区。

信号量的互斥操作

不管是谁先进入临界区操作临界区的资源,其它的线程就没办法来操作;只有等到操作完临界区的线程释放资源,其它的线程才能进行操作;每一个时刻只有一个线程可以操作临界区。

获取信号量函数

第一个参数为信号量的结构体指针

第二个参数为time,我们通过time可以知道如果线程获取不到信号量的时候是处于什么样的状态(如果为RT_WAITING_FOREVER就进入休眠状态一直等待信号量;RT_WAITING_NO为非阻塞的模式,如果线程获取不到信号量就直接返回,不会休眠;再然后其它的time值就是自己设置的等待时间:注意时间要大于0)

释放信号量

释放信号量可以唤醒挂起在该信号量上的线程

/*** This function will release a semaphore, ifthere are threads suspended on* semaphore, it will be waked up.** @param sem the semaphore object** @return the error code*/
rt_err_t rt_sem_release(rt_sem_t sem)

信号量同步实例

(1)首先创建一个全局变量flags

(2)然后创建两个线程,让它们都能够操作到flags(我们将线程的优先级设置为相同优先级,这样才可能会导致竞态产生)

(3)此时我们想实现线程1和线程2的同步操作,即先执行线程1然后执行线程2,顺序执行

原理:比如说我们现在有两个信号量,信号量1初始化value为1,信号量2初始化value为0。线程1进入临界空间以后首先获取信号量1(信号量value大于1,获取成功),等线程1执行完之后信号量1会自动减1,然后释放信号量2,信号量2加1;此时线程2可以获取到信号量2,开始执行,执行完之后信号量2自动减1,然后释放信号量1,信号量1加1,然后线程1又开始执行了。按照顺序依次执行。

(4)创建两个信号量sem1和sem2

(5)完善线程执行函数:线程1先休眠8秒,线程2执行完一次再休眠2秒

(6)main函数中启动两个线程

(7)实验现象

烧写程序上电后,发现两个线程都处于挂起状态

因为线程1处于8秒的延时状态,而线程2此时无法获取到信号量

运行完效果:两个线程按顺序交替操作,flags的值在0-1跳转

互斥量(互斥锁)

        互斥量体现的是排他性,也是解决多线程同时操作临界区临界资源导致的竟态的一种方法。(类似于特殊的信号量——二值信号量)

        区别:信号量可由不同线程释放,互斥量只能由同一线程进行释放。

互斥量的使用和管理

互斥量的操作包含:创建 / 初始化互斥量、获取互斥量(相对于上锁)、释放互斥量(相对于解锁)、删除 / 脱离互斥量

动态创建互斥量

rt_mutex_create函数用于创建互斥量

参数1:信号量名字

参数2:#define RT_IPC_FLAG_FIFO 0x00 //按照线程先进先出获取信号量资源

             #define RT_IPC_FLAG_PRIO 0x01 //按照线程优先级获取信号量资源

返回值为结构体指针变量rt_mutex_t

#ifdef RT_USING_HEAP
/*** This function will create a mutex from system resource** @param name the name of mutex* @param flag the flag of mutex** @return the created mutex, RT_NULL on error happen** @see rt_mutex_init*/
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)

不再使用互斥量时,通过删除互斥量以释放系统资源,适用于动态创建的互斥量

当删除一个互斥量时,所有等待此互斥量的线程都将被唤醒,等待线程获得的返回值是

- RT_ERROR

/*** This function will delete a mutex object andrelease the memory** @param mutex the mutex object** @return the error code** @see rt_mutex_detach*/
rt_err_t rt_mutex_delete(rt_mutex_t mutex)
动态创建过程

静态创建互斥量

初始化和脱离互斥量

注意传入的第一个参数是结构体变量的地址

/*** This function will initialize a mutex andput it under control of resource* management.** @param mutex the mutex object* @param name the name of mutex* @param flag the flag of mutex** @return the operation status, RT_EOK onsuccessful*/
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)

使用该函数接口后,内核先唤醒所有挂在该互斥量上的线程(线程的返回值是

-RT_ERROR) ,然后系统将该互斥量从内核对象管理器中脱离。

/*** This function will detach a mutex fromresource management** @param mutex the mutex object** @return the operation status, RT_EOK onsuccessful** @see rt_mutex_delete*/
rt_err_t rt_mutex_detach(rt_mutex_t mutex)
静态创建过程

一般创建好互斥锁,是不会去删除或者分离的,如果要删除则分别使用delete和detach

获取互斥量

/*** This function will take a mutex, if themutex is unavailable, the* thread shall wait for a specified time.** @param mutex the mutex object* @param time the waiting time** @return the error code*/
rt_err_t rt_mutex_take(rt_mutex_tmutex, rt_int32_t time)

释放互斥量

/*** This function will release a mutex, if thereare threads suspended on mutex,* it will be waked up.** @param mutex the mutex object** @return the error code*/
rt_err_t rt_mutex_release(rt_mutex_tmutex)

互斥锁实例

(1)首先创建两个临界资源flag1和flag2

(2)创建一个互斥锁

(3)创建两个线程

(4)在如下的情况下我们可以发现运行时,每次打印出来的flag1和flag2的值是不相等的

如果我们想要实现每次打印的两个值相等,则要确保线程1执行完成一次循环之后再执行线程2(即线程不会因为休眠挂起而被另一个线程操作临界区资源)。我们将线程1的while(1)设为临界区,进行上锁

(5)为相应临界区上锁和解锁

(6)结果现象

从输出的实验结果可以得知如果有两个线程使用同一把锁,则线程B必须等线程A执行完上锁和解锁及临界区的操作,才可以执行上锁操作,并继续往下执行,否则上锁失败,线程B就会进入挂起状态等待线程A解锁方可唤醒

事件集

        事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。

一个线程和多个事件的关系可设置为:

        其中任意一个事件唤醒 线程,或几个事件都到达后唤醒线程,多个事件集合可以用一个32bit无符号整型变量来表示,变量的每一位代表一个事件,线程通过"逻辑与"或"逻辑或"将一个或多个事件关联起来,形成事件组合。

RT-Thread 定义的事件集有以下特点:

  • 事件只与线程相关,事件间相互独立
  • 事件仅用于同步,不提供数据传输功能
  • 事件无排队性,即多次向线程发送同一事件(如果线程还未来得及读走),其效果等同于只发送一次

动态创建事件集

创建和删除

/** event structure*/
struct rt_event
{struct rt_ipc_object parent;     /**< inherit from ipc_object */rt_uint32_t          set;         /**< event set */
};
typedef struct rt_event *rt_event_t;/*** This function will create an event objectfrom system resource** @param name the name of event* @param flag the flag of eventRT_IPC_FLAG_FIFO RT_IPC_FLAG_PRIO** @return the created event, RT_NULL on errorhappen*/
rt_event_t rt_event_create(const char*name, rt_uint8_t flag)
/*** This function will delete an event objectand release the memory** @param event the event object** @return the error code*/
rt_err_t rt_event_delete(rt_event_tevent)

静态创建事件集

初始化和脱离

/*** This function will initialize an event andput it under control of resource* management.** @param event the event object* @param name the name of event* @param flag the flag of event** @return the operation status, RT_EOK onsuccessful*/
rt_err_t rt_event_init(rt_event_tevent, const char *name, rt_uint8_t flag)
/*** This function will detach an event objectfrom resource management** @param event the event object** @return the operation status, RT_EOK onsuccessful*/
rt_err_t rt_event_detach(rt_event_tevent)

事件集创建过程

(与前面类似,这里以动态为例)

事件集实现线程同步

事件集有多个事件,能够完成多个事件的同步。之前在完成线程同步的时候用的是信号量,但用到的是多个信号量才能完成线程的同步。而现在我们可以通过一个事件集来完成线程的同步。

事件集用的集合的类型是无符号32bit整形,事件的占位是一个事件占用一个位。所以一个集合里面支持32个事件。

发送事件

该函数给事件集对象发送一个事件,如果存在线程在事件集对象上挂起,它将会被唤醒

第一个参数为事件的结构体指针(事件集对象)

第二个参数为具体的事件值

/*** This function will send an event to the event object, if there are threads* suspended on event object, it will be wakedup.** @param event the event object* @param set the event set** @return the error code*/
rt_err_t rt_event_send(rt_event_tevent, rt_uint32_t set)

接收事件

该函数的功能是从事件集对象里面接收一个事件,如果事件是不可用的,线程将进入休眠(挂起状态)

第二个参数为指定具体接收是哪个事件

第三个参数为接收的操作,设置与和或的关系,还有是否设置在接收完某个事件后对位进行清除

第四个参数设置等待时间,与前面相同

第五个参数用于接收事件的值,如果不关心就不设置

/*** This function will receive an event from event object, if the event is* unavailable, the thread shall wait for aspecified time.** @param event the fast event object* @param set the interested event set* @param option the receive option, eitherRT_EVENT_FLAG_AND or*       RT_EVENT_FLAG_OR should be set. RT_EVENT_FLAG_CLEAR * @param timeout the waiting time  RT_WAITING_FOREVER RT_WAITING_NO* @param recved the received event, if youdon't care, RT_NULL can be set.** @return the error code*/
rt_err_trt_event_recv(rt_event_t   event,rt_uint32_t  set,rt_uint8_t   option,rt_int32_t   timeout,rt_uint32_t *recved)

实现原理

我们要用事件集实现三个线程的同步

如果采用信号量的话,我们需要三个信号。而采用事件集,我们只要使用三个事件位即可。

以事件2为例,当调度器调度到线程2,此时发现线程2没有接收到事件2,就无法往下执行,它就会挂起,从而线程3也无法接收到事件3。因此我们可以手动在main函数中手动发送一个事件,从而触发一个线程可以正常执行。

我们再使用事件集的时候,还可以用到or和and的关系。and:比如可以设置事件1和事件2同时满足的,线程1才可以执行;or:比如设置事件1或事件2有一个满足,线程1就可以执行

实现过程

(1)创建事件集

(3)创建三个线程

(4)发送、接收事件使用

在main中手动发送

(5)实验效果:每秒钟按照1、2、3的顺序执行

事件集实现进程同步源码

#include <rtthread.h>#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>rt_event_t event1;
rt_thread_t th1,th2,th3;#define EVENT_FLAGS_1 (0x01<<0)
#define EVENT_FLAGS_2 (0x01<<1)
#define EVENT_FLAGS_3 (0x01<<2)
void th1_entry(void *parameter)
{while(1){rt_event_recv(event1,EVNET_FLAGS_1,RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_AND,\RT_WAITING_FOREVER,NULL);rt_kprintf("th1_entry...\n");rt_event_send(event1,EVENT_FLAGS_2);rt_thread_mdelay(1000);}
}
void th2_entry(void *parameter)
{while(1){rt_event_recv(event1,EVNET_FLAGS_2,RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_AND,\RT_WAITING_FOREVER,NULL);rt_kprintf("th2_entry...\n");rt_event_send(event1,EVENT_FLAGS_3);rt_thread_mdelay(1000);}
}
void th3_entry(void *parameter)
{while(1){rt_event_recv(event1,EVNET_FLAGS_3,RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_AND,\RT_WAITING_FOREVER,NULL);rt_kprintf("th3_entry...\n");rt_event_send(event1,EVENT_FLAGS_1);rt_thread_mdelay(1000);}
}
int main(void)
{event1 = rt_event_create("set1", RT_IPC_FLAG_FIFO);if(event1 == RT_NULL){LOG_E("rt_event_create failed...\n");return -ENOMEM;}LOG_D("rt_event_create succeed...\n");th1 = rt_thread_create("th1",th1_entry,RT_NULL,512,10,5);if(th1 == RT_NULL){LOG_E("th1 rt_thread_create failed...\n");return -ENOMEM;}th2 = rt_thread_create("th2",th2_entry,RT_NULL,512,10,5);if(th2 == RT_NULL){LOG_E("th2 rt_thread_create failed...\n");return -ENOMEM;}th3 = rt_thread_create("th3",th3_entry,RT_NULL,512,10,5);if(th3 == RT_NULL){LOG_E("th3 rt_thread_create failed...\n");return -ENOMEM;}rt_thread_startup(th1);rt_thread_startup(th3);rt_thread_startup(th2);rt_event_send(event1,EVENT_FLAGS_1);return RT_EOK;
}

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

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

相关文章

【网络编程·网络层】IP协议

目录 一、IP协议的概念 二、IP协议的报头 1、四位首部长度 2、16位总长度&#xff08;解包&#xff09; 3、8位协议&#xff08;分用&#xff09; 4、16位首部校验和 5、8位生存时间 6、32位源IP和32位目的IP 7、4位版本/8位服务类型 8、16位标识 9、3位标志 10、1…

无涯教程-Perl - lock函数

描述 此函数将咨询锁放在共享变量或THING中包含的引用对象上,直到该锁超出范围。 lock()是一个"弱关键字":这意味着,如果您在调用该函数之前已通过该名称定义了该函数,则将改为调用该函数。 语法 以下是此函数的简单语法- lock THING返回值 此函数不返回任何值…

Python接口自动化测试之UnitTest详解

基本概念 UnitTest单元测试框架是受到JUnit的启发&#xff0c;与其他语言中的主流单元测试框架有着相似的风格。其支持测试自动化&#xff0c;配置共享和关机代码测试。支持将测试样例聚合到测试集中&#xff0c;并将测试与报告框架独立。 它分为四个部分test fixture、TestC…

武汉大学计算机学院2010情景剧,武汉大学金秋情景剧大赛精彩落幕(组图)

作为金秋艺术节的“重头戏”&#xff0c;留香行板--情景剧大赛决赛于11月5日在信息学部大学生活动中心隆重开演。15个学院先后表演了精心编排的情景剧&#xff0c;最终经过激烈的角逐&#xff0c;新闻与传播学院凭借《方向》成功蝉联&#xff0c;与经济管理学院的《爱的礼赞》一…

快来带您了解中秋节的前世今生

中秋节是中国传统的节日&#xff0c;落在农历八月十五&#xff0c;一般是公历九月或十月上旬。 按中国古代历法的解释&#xff0c;八月是秋季的第二个月&#xff0c;称“仲秋”&#xff0c;八月十五又在仲秋之中&#xff0c;所以叫“中秋”。2022年&#xff0c;中秋节落在9月10…

MySQL数据库 *实验16 变量表达式和函数

只要你有想去的地方&#xff0c;全世界都会为你让路~ 1.定义一个变量x存放以下字符串 刘王张赵李钱朱何孙曾陈吴黄刘邓周毛江胡’&#xff1b; 2.定义一个变量len1存放x字符串的长度&#xff1b; 3.定义一个变量m1存放以下字符串 ‘依秋香巧花紫萱莉玉芳菊碧丽念雅红燕艳莲…

女孩砖厂打工照顾弟妹被网友拍下(图)

8日下午&#xff0c;网友“土家风情郎”在论坛贴出一组图片&#xff0c;反映贵州一名叫张倩倩的小女孩在砖厂打暑期工&#xff0c;还要照顾三个弟妹的情况&#xff0c;该帖发出后&#xff0c;许多网友赞赏女孩懂事。 年纪小小的她&#xff0c;有着同龄人少有的沉着淡定。 生活不…

opencv基础59-霍夫变换原理讲解及示例-cv2.HoughLines()->(直线,圆形检测)

霍夫变换是一种在图像中寻找直线、圆形以及其他简单形状的方法。霍夫变换采用类似于投票的方式来获取当前图像内的形状集合&#xff0c;该变换由 Paul Hough&#xff08;霍夫&#xff09;于 1962 年首次提出。 最初的霍夫变换只能用于检测直线&#xff0c;经过发展后&#xff0…

直播预告|EasyV全新倾斜摄影组件上线!提升大规模、高精度实景建模效率

倾斜摄影&#xff0c;也被称为斜摄影或倾斜摄影测量&#xff0c;是一种高精度、高分辨率的遥感技术&#xff0c;用于获取地表地貌、建筑物、自然环境等目标的三维信息。在城市级数字孪生可视化建设过程中&#xff0c;通常会使用倾斜摄影技术以增强地理信息分析和虚拟建模的能力…

线性回归学习总结

一 、引文 1 回归分析 回归是统计学上用来分析数据的方法&#xff0c;以了解两个或多个变量之前的关系。通常是建立被解释变量Y和解释变量X之间关系的模型。回归分析的最早形式是最小二乘法。 勒让德和高斯都将该方法应用于从天文观测中确定关于太阳的物体的轨道&#xff08;…

Java-低代码平台使用H2内存数据库

一、引言 作者目前在做的平台使用到了H2&#xff0c;这里介绍下使用场景、使用方式&#xff0c;出于以下两个原因会使用H2: 1、平台化的项目一般是用户使用脚本或者sql进行通用的执行&#xff0c;这样可以实现低代码平台&#xff0c;不需要管理类之间的引入、依赖、编译&#x…

制造业企业数字化转型之设备数据采集

导 读 ( 文/ 1894 ) 随着信息技术的快速发展和制造业的转型升级&#xff0c;企业数字化转型已成为保持竞争力和实现可持续发展的关键。在数字化转型过程中&#xff0c;设备数据采集作为重要的一环&#xff0c;发挥着关键的作用。设备数据采集通过收集、分析和利用设备所产生的数…

怎样找回e盘删除的文件夹?分享三种恢复方法

我们都知道&#xff0c;电脑可以划分多个区域来存储数据&#xff0c;例如C盘、D盘、E盘、F盘等&#xff0c;而不论是存储在哪个磁盘&#xff0c;都容易出现文件丢失的问题&#xff0c;那么电脑e盘文件夹删除了怎么恢复呢&#xff1f;下面小编分享一些方法&#xff0c;一起来看下…

C#多线程开发详解

C#多线程开发详解 持续更新中。。。。。一、为什么要使用多线程开发1.提高性能2.响应性3.资源利用4.任务分解5.并行计算6.实时处理 二、多线程开发缺点1.竞态条件2.死锁和饥饿3.调试复杂性4.上下文切换开销5.线程安全性 三、多线程开发涉及的相关概念常用概念(1)lock(2)查看当前…

基于计算机的色彩描述

计算机中的色彩描述方法主要有RGB、CMY、Lab、HSB、sRGB、YUV、YCbCr、YIQ等。 CMYK色彩模式主要用于使用色料呈色的彩色设备。CMYK模式实质指的是再现色彩时单位面积上含C、M、Y、K点的百分比。 Lab色彩模式是建立在CIE 1976 L*a*b 颜色空间基础上的色彩模式&#xff0c;包含…

HSV色彩范围

一般对颜色空间的图像进行有效处理都是在HSV空间进行的&#xff0c;然后对于基本色中对应的HSV分量需要给定一个严格的范围&#xff0c;下面是通过实验计算的模糊范围&#xff08;准确的范围在网上都没有给出&#xff09;。 H: 0 — 180 S: 0 — 255 V: 0 — 255 此处把部分红色…

OBS推流时的视频色彩相关参数设置

在使用OBS进行推流直播时&#xff0c;特别是采集卡采集摄像机信号进行推流直播时&#xff0c;我们可能会遇到这样的问题&#xff1a;   1.为什么流信号与源信号相比有色彩偏差&#xff1f;   2.明暗对比较大的视频信号&#xff0c;比如有树荫和太阳&#xff0c;在摄像机上可…

视频产生的本质及色彩空间:RGB 和 YUV

一、前言 在前面几篇文章中&#xff0c;我们完成了音频相关基础知识的学习&#xff0c;从今天开始&#xff0c;我们要暂别音频&#xff0c;继续学习视频相关基础内容。 虽说声音在我们日常的生活、工作、娱乐过程中&#xff0c;发挥着不可替代的作用&#xff0c;但人们常说&a…

彩色图像色彩模型

彩色图像处理可分为两个主要领域&#xff1a;全彩色处理和伪彩色处理。全彩色处理通常要求图像用全彩色传感器获取&#xff0c;伪彩色处理是对一种特定的单色灰度活灰度范围赋予一种颜色。 定义&#xff1a; 亮度&#xff1a;具体表达了无色的强度概念&#xff0c;显示图像的…

ArcGIS基础:分级色彩和换行标注(VbCrLf)操作(以制作社会经济分析图为例)

我们需要用到的实验数据如下&#xff1a; 村&#xff08;点数据和面数据&#xff09;&#xff0c;主要属性就是【人口数】、【经济总量】&#xff0c;如下图所示。 点数据的要使用的两个字段【人口数】、【经济总量】如下&#xff1a; 面数据的要使用的两个字段【人口数】、【…