(数字图像处理MATLAB+Python)第九章图像形态学运算-第一、二节:形态学基础和二值形态学运算

news2024/11/16 3:50:31

文章目录

  • 一:形态学基础
    • (1)结构元素
    • (2)程序
  • 二:二值形态学的基础运算
    • (1)基本形态变换
      • A:膨胀运算
        • ①:概述
        • ②:示例
        • ③:程序
      • B:腐蚀运算
        • ①:概述
        • ②:示例
        • ③:程序
        • 膨胀和腐蚀性质
    • (2)复合形态变换
      • A:开、闭运算定义
      • B:开、闭运算效果
      • C:开、闭运算性质
      • D:程序

一:形态学基础

形态学:是图像处理中的一种基本方法,用于对图像中的形状和结构进行分析和处理。形态学基于数学形态学的理论,利用结构元素和形态学运算来改变和提取图像中的形状、边界和纹理等特征

形态学运算:就是用结构元素对图像集合进行操作,观察图像中各部分关系,从而提取有用特征进行分析和描述,以达到对图像进行分析和识别的目的。下面是常见的形态学运算

  • 膨胀(Dialation)
  • 腐蚀(Eroision)
  • 开运算(Opening)
  • 闭运算(Closing)
  • 击中击不中变换(Hit-or-Miss Transform)

(1)结构元素

结构元素:是形态学运算中的一个重要概念,它是一个小的固定形状模板或窗口,用于在形态学运算中与图像进行卷积操作。结构元素可以是各种形状,例如矩形、圆形、十字形等,其选择取决于所需的操作和应用场景。结构元素的大小和形状对形态学运算的结果具有重要影响。较小的结构元素可以更好地捕捉图像中的细节和小尺度特征,而较大的结构元素则更适用于涉及较大目标的操作。通常,结构元素被定义为二值图像,其中前景像素表示结构元素的形状,背景像素表示结构元素外部

在这里插入图片描述

选取结构元素需要遵循以下原则

  • 结构元素的几何结构要比原图像简单且有界,且尺寸要明显小于目标图像的尺寸
  • 结构元素的形状最好具有某种凸性
  • 对于每个结构元素,指定一个原点,作为结构元素参与形态学运算的“参考点”

所有形态学处理都基于填放结构元素的概念。所谓的填放,就是用不同的方法把结构元素放在原图像的内部,在结构元素的填放中引出一系列图像的特性。不同的结构元素和不同的形态学变换可以得到图像不同的处理作用结果

(2)程序

如下:生成一个菱形结构元素

在这里插入图片描述


matllab实现

strel函数是用于创建结构元素的函数,用于形态学图像处理中的运算。结构元素由strel函数根据指定的形状和尺寸创建,并可以用于膨胀、腐蚀、开运算、闭运算等形态学操作。其语法格式如下

se = strel(shape, parameters)

参数

  • shape参数指定了结构元素的形状,可以是以下几种形式之一:

    • 'square':正方形结构元素
    • 'rectangle':矩形结构元素
    • 'disk':圆形结构元素
    • 'line':线形结构元素
  • parameters参数是可选的,用于指定结构元素的大小或其他特定参数,具体取决于所选的形状

strel函数返回一个结构元素对象 se,该对象可以用于对图像进行形态学操作。结构元素对象具有一些常用的方法,如膨胀(dilate)、腐蚀(erode)、开运算(open)、闭运算(close)等,可以通过调用这些方法来执行对应的形态学操作

SE = strel('diamond',3);
GN=getnhood(SE)%获取结构元素的邻域
figure,imshow(GN,[]); 

Python实现

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 创建一个菱形结构元素
SE = cv2.getStructuringElement(cv2.MORPH_CROSS, (3, 3))
GN = SE  # 获取结构元素的邻域

# 显示邻域图像
plt.imshow(GN, cmap='gray', vmin=0, vmax=1)
plt.axis('off')
plt.show()

二:二值形态学的基础运算

(1)基本形态变换

A:膨胀运算

①:概述

膨胀运算:是形态学运算中的一种基本操作,用于扩展图像中的明亮区域或增加目标的大小。膨胀运算可以通过结构元素与图像进行卷积操作来实现。集合 X X X用结构元素 S S S来膨胀记为 X ⊕ S \boldsymbol{X} \oplus \boldsymbol{S} XS

X ⊕ S = { x ∣ [ ( S ^ ) x ∩ X ] ≠ ∅ } \boldsymbol{X} \oplus \boldsymbol{S}=\left\{\boldsymbol{x} \mid\left[(\widehat{\boldsymbol{S}})_{\boldsymbol{x}} \cap \boldsymbol{X}\right] \neq \varnothing\right\} XS={x[(S )xX]=}

其含义为:对结构元素 S S S作关于原点的映射,所得映射平移为 x x x,形成新的集合为 ( S ^ ) x (\widehat{\boldsymbol{S}})_{\boldsymbol{x}} (S )x,与集合 X X X相交不为空集时结构元素 S S S的参考点的集合即为 X X X S S S膨胀所得到的集合

膨胀运算的过程如下

  1. 将结构元素 S S S的中心放置在图像X的一个像素位置上
  2. 对于结构元素 S S S中的每个元素,如果该元素对应的图像 X X X的相应位置上有一个非零值(即白色像素),则将该元素的值添加到结果图像的相应位置上
  3. 重复步骤1和2,直到结构元素 S S S覆盖完整个图像 X X X
  4. 最终得到的结果图像表示了图像 X X X中所有与结构元素 S S S有交集的像素的并集

膨胀运算的效果是将图像中的边界扩展并填充空洞,增加目标的大小。它可以用于去除小的噪点、连接断开的边界、平滑图像的边缘等应用

膨胀运算代码实现如下

Image=imread('menu.bmp');             %打开图像
BW=im2bw(Image);                   %转换为二值图像
figure,imshow(BW);
[h w]=size(BW);                      %获取图像尺寸
result=zeros(h,w);                     %定义输出图像,初始化为0
for x=2:w-1
    for y=2:h-1                      %扫描图像每一点,即结构元素移动到每一个位置
        for m=-1:1
            for n=-1:1               %当前点周围3×3范围,即结构元素为3×3大小
               if BW(y+n,x+m)       %结构元素所覆盖3×3范围内有像素点为1,即交集不为空
                   result(y,x)=1;      %将参考点记录为前景点
                   break;
               end
            end
        end
    end
end
figure,imshow(result);title('二值图像膨胀');
SE=strel('square',3);                 %创建结构元素
result1=imdilate(BW,SE);             %膨胀运算
figure,imshow(result1);title('二值图像imdilate');


②:示例

示例一:图(a)是一副二值图像,深色“1”部分为目标集合 X X X 。图(b)中深色“1”部分为结构元素 S S S(标有“+”处为原点,即结构元素的参考点)。求 X ⊕ S \boldsymbol{X} \oplus \boldsymbol{S} XS

在这里插入图片描述

:图©中深色“1”部分为结构元素 S S S的映射 S ^ \widehat{S} S 。(d)中深色部分;其中,浅灰色“1”部分表示集合 X X X;深灰色“1”部分表示为膨胀(扩大)部分。则整个深色阴影部分就为集合 X ⊕ S \boldsymbol{X} \oplus \boldsymbol{S} XS

在这里插入图片描述


示例二:图(a)中深色“1”部分为目标集合 X X X ,图(b)中深色“1”部分为结构元素 S S S。 求 X ⊕ S \boldsymbol{X} \oplus \boldsymbol{S} XS
在这里插入图片描述

:(c)将 S S S映射为 S ^ \widehat{S} S ,将 S ^ \widehat{S} S X X X上移动,记录交集不为空时结构元素参考点位置,得(d)所示深色阴影部分为膨胀后结果。可看出,目标集合经膨胀后不仅面积扩大,而且相邻两个孤立成分连接
在这里插入图片描述

③:程序

如下

在这里插入图片描述


matlab实现

Image=imread('menu.bmp');
BW=im2bw(Image);
SE=strel('square',3); %创建结构元素
result=imdilate(BW,SE); %膨胀运算
figure,imshow(result);

python实现

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图像
Image = cv2.imread('menu.bmp', 0)

# 二值化处理
ret, BW = cv2.threshold(Image, 127, 255, cv2.THRESH_BINARY)

# 创建一个3x3的正方形结构元素
SE = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 膨胀运算
result = cv2.dilate(BW, SE)

# 显示结果图像
plt.imshow(result, cmap='gray')
plt.axis('off')
plt.show()

B:腐蚀运算

①:概述

腐蚀运算:是形态学图像处理中的一种基本运算,用于缩小或消除图像中边界或物体的细节。集合 X X X用结构元素 S S S来腐蚀记为 X ⊖ S X \ominus S XS

X ⊖ S = { x ∣ ( S ) x ⊆ X } \boldsymbol{X} \ominus \boldsymbol{S}=\left\{\boldsymbol{x} \mid(\boldsymbol{S})_{\boldsymbol{x}} \subseteq \boldsymbol{X}\right\} XS={x(S)xX}
其含义为:若结构元素 S S S平移 x x x后完全包括在集合 X X X中,记录 S S S的参考点位置,所得集合为 S S S腐蚀 X X X的结果

腐蚀运算代码实现如下

Image=imread('menu.bmp');     %打开图像
BW=im2bw(Image);                %转换为二值图像
figure,imshow(BW);
[h w]=size(BW);                  %获取图像尺寸
result=ones(h,w);                %定义输出图像,初始化为1
for x=2:w-1
    for y=2:h-1                    %扫描图像每一点,即结构元素移动到每一个位置
        for m=-1:1
            for n=-1:1             %当前点周围3×3范围,即3×3结构元素所覆盖范围
               if BW(y+n,x+m)==0  %该范围内有像素点为0,即该位置不能完全包含结构元素
                   result(y,x)=0;  %将参考点记录为背景点,即腐蚀掉
                   break;
               end
            end
        end
    end
end
figure,imshow(result); title('二值图像腐蚀');
SE=strel('square',3);             %创建结构元素
result=imerode(BW,SE);         %腐蚀运算
figure,imshow(result); title('二值图像imerode');

②:示例

示例:图(a)是一副二值图像,深色“1”部分为目标集合 X X X 。图(b)中深色“1”部分为结构元素 S S S。求 X ⊖ S \boldsymbol{X} \ominus \boldsymbol{S} XS
在这里插入图片描述

:当 S S S参考点位于图(c)中红框“1”部分时, ( S ) x ⊆ (S)_x\subseteq (S)xX,则 X ⊖ S X \ominus S XS为图(d)中深灰色“1”部分。白色“0”部分为腐蚀消失部分

③:程序

如下
在这里插入图片描述


matlab实现

Image=imread('menu.bmp');
BW=im2bw(Image);
SE=strel('square',3); %创建结构元素
result=imerode(BW,SE); %腐蚀运算
figure,imshow(result);

python实现

import cv2
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('menu.bmp', cv2.IMREAD_GRAYSCALE)

# 二值化
ret, bw = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 创建结构元素
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 腐蚀运算
result = cv2.erode(bw, se)

# 显示结果图像
plt.imshow(result, cmap='gray')
plt.show()

膨胀和腐蚀性质

性质1:膨胀和腐蚀运算是关于集合补和映射的对偶关系

( X Θ S ) c = X c ⊕ S ^ ( X ⊕ S ) c = X c S ^ \begin{array}{l}(X \Theta \boldsymbol{S})^{\boldsymbol{c}}=X^{\boldsymbol{c}} \oplus \hat{\boldsymbol{S}} \\(X \oplus \boldsymbol{S})^{\boldsymbol{c}}=X^{\boldsymbol{c}} \boldsymbol{\hat { S }}\end{array} (XΘS)c=XcS^(XS)c=XcS^

性质2:膨胀运算具有互换性,腐蚀运算不具有

( X ⊕ S 1 ) ⊕ S 2 = ( X ⊕ S 2 ) ⊕ S 1 \left(X \oplus S_{1}\right) \oplus S_{2}=\left(X \oplus S_{2}\right) \oplus S_{1} (XS1)S2=(XS2)S1

性质3:膨胀运算具有结合性

若 S = S 1 ⊕ S 2 , 则有 : X ⊕ S = X ⊕ ( S 1 ⊕ S 2 ) = ( X ⊕ S 1 ) ⊕ S 2 若 S=S_{1} \oplus S_{2} , 则有:X \oplus S=X \oplus\left(S_{1} \oplus S_{2}\right)=\left(X \oplus S_{1}\right) \oplus S_{2} S=S1S2,则有:XS=X(S1S2)=(XS1)S2

性质4:膨胀和腐蚀运算具有增长性

X ⊆ Y ⇒ ( X ⊕ S ) ⊆ ( Y ⊕ S ) X ⊆ Y ⇒ ( X ⊖ S ) ⊆ ( Y ⊖ S ) \begin{array}{l}X \subseteq Y \Rightarrow(X \oplus S) \subseteq(Y \oplus S) \\X \subseteq Y \Rightarrow(X \ominus S) \subseteq(Y \ominus S)\end{array} XY(XS)(YS)XY(XS)(YS)

(2)复合形态变换

一般情况下,膨胀和腐蚀不是互为逆运算的。膨胀和腐蚀进行级连结合使用,产生新的形态变换,即开运算(Opening)和闭运算(Closing)

A:开、闭运算定义

开运算:用结构元素对图像先腐蚀,再膨胀

X ∘ S = ( X ⊖ S ) ⊕ S \boldsymbol{X} \circ \boldsymbol{S}=(\boldsymbol{X} \ominus \boldsymbol{S}) \oplus \boldsymbol{S} XS=(XS)S

闭运算:用结构元素对图像先膨胀,再腐蚀

X ⋅ S = ( X ⊕ S ) ⊖ S \boldsymbol{X} \cdot \boldsymbol{S}=(\boldsymbol{X} \oplus \boldsymbol{S}) \ominus \boldsymbol{S} XS=(XS)S

B:开、闭运算效果

开运算效果

  • 删除小物体(滤掉突刺)
  • 将物体拆分为小物体(切断细长搭接)起分离作用
  • 平滑大物体边界而不明显改变它们面积(平滑图像轮廓)

闭运算效果

  • 填充物体的裂缝和小洞
  • 连相近物体(搭接短的间断)起连通补接作用
  • 平滑大物体边界而不明显改变它们面积(平滑图像轮廓)

C:开、闭运算性质

性质1:开运算和闭运算都具有增长性

X ⊆ Y ⇒ { ( X ∘ S ) ⊆ Y ( X ⋅ S ) ⊆ Y X \subseteq Y \Rightarrow\left\{\begin{array}{l}(X \circ S) \subseteq Y \\(X \cdot S) \subseteq Y\end{array}\right. XY{(XS)Y(XS)Y

性质2:开运算是非外延的,而闭运算是外延的

X ∘ S ⊆ X X ⊆ X ⋅ S \begin{array}{l}\boldsymbol{X} \circ \boldsymbol{S} \subseteq \boldsymbol{X} \\\boldsymbol{X} \subseteq \boldsymbol{X} \cdot \boldsymbol{S}\end{array} XSXXXS

性质3:开运算和闭运算都具有同前性

( X ∘ S ) ∘ S = X ∘ S ( X ⋅ S ) ⋅ S = X ⋅ S \begin{array}{l}(X \circ S) \circ S=X \circ S \\(X \cdot S) \cdot S=X \cdot S\end{array} (XS)S=XS(XS)S=XS

性质4:开运算和闭运算都具有对偶性

( X ∘ S ) c = X c ⋅ S ^ ( X ⋅ S ) c = X c ∘ S ^ \begin{array}{l}(X \circ S)^{c}=X^{c} \cdot \widehat{S} \\(X \cdot S)^{c}=X^{c} \circ \widehat{S}\end{array} (XS)c=XcS (XS)c=XcS

D:程序

如下:

在这里插入图片描述


matlab实现

Image=imread('A.bmp');
BW=im2bw(Image);
SE=strel('square',3);
result1=imopen (BW,SE),SE);
result2=imclose(BW,SE),SE);
figure,imshow(result1) ;title('开运算');
figure,imshow(result2); ;title('闭运算');

python实现

import cv2
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('A.bmp', cv2.IMREAD_GRAYSCALE)

# 二值化
ret, bw = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

# 创建结构元素
se = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 开运算
result1 = cv2.morphologyEx(bw, cv2.MORPH_OPEN, se)

# 闭运算
result2 = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, se)

# 显示结果图像
plt.subplot(1, 2, 1)
plt.imshow(result1, cmap='gray')
plt.title('开运算')

plt.subplot(1, 2, 2)
plt.imshow(result2, cmap='gray')
plt.title('闭运算')

plt.show()

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

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

相关文章

CleanMyMac X4.13.4中文版下载及使用教程

随着Mac电脑的广泛普及,越来越多的用户开始关注如何保持自己电脑的快速运行。众所周知,Mac电脑的性能和稳定性得到了广泛认可。但是,随着使用时间的增加和数据的增加,任何电脑都可能变得缓慢和难以使用。为了解决这一问题&#xf…

2-《Java进阶》

2-《Java进阶》 一. java多线程(非常重要)1.1. 线程java多线程实现方式主要有:1.继承Thread 2.实现Runnable3.实现CallableRunnable 与 Callable的区别:1.2. 线程的状态有哪些?1.3. 线程的状态转换及控制1.4. Java如何…

SeaweedFs使用-通过http接口实现文件操作

通过http接口实现文件操作 SeaweedFs可通过filer的http接口/master中的http接口来进行文件上传 1.通过master的接口进行上传文件 通过各种方式进行请求接口:http://localhost:9333/submit, ip和端口号是master服务的信息。此接口通过post请求方式将文件的二进制流…

3-《安卓基础》

3-《安卓基础》 1.Android系统架构2.四大组件1Activity1.1 生命周期1.2. Activity四种启动模式1.3.Activity任务栈的概念1.3.Activity的显示启动和隐示启动1.4.scheme使用场景,协议格式,如何使用?1.5.activty间传递数据的方式1.6.跨进程启动A…

网络安全-kail linux渗透测试(基础篇)

渗透测试是一个非常广的课程,我们首先要做的是在某个方向精通,再在其他方面也要有涉猎。 大部分的漏洞是国外挖掘的。 一、推荐研究书籍: Metasploit浚透测试指南》肯尼(行业经典) 诸葛建伟翻译 《Metasloit渗透测试魔鬼训练营》诸葛建伟…

运用pyecharts制作可视化大屏(代码展示及效果图-动图)

一、Matplotlib绘图 折线图 import matplotlib.pyplot as plt # 调用画图库 plt.rcParams[font.sans-serif] [SimHei] # 设置成可以显示中文,字体为黑体 plt.figure(figsize(12,8)) # 调整图片尺寸 x [周一,周二,周三,周四,周五,周六,周日] # 设置x轴数据 y [401…

物联网网络通讯知识

RTU是什么 RTU英文全称Remote Terminal Units,中文全称为远程终端单元。远程终端设备(RTU)是安装在远程现场的电子设备,用来监视和测量安装在远程现场的传感器和设备。通俗理解就是能够编程的还可以将数据传输到服务器的工具。RTU内部是包含通讯模块的&…

4、详细版易学版TypeScript - 元组 枚举

一、元组(Tuple) 数组&#xff1a;合并了相同类型的对象 const myArr: Array<number> [1, 2, 3]; 元组(Tuple)&#xff1a;合并了不同类型的对象 // 定义元组时就要确定好数据的类型&#xff0c;并一一对应 const tuple: [number, string] [12, "hi"]; // 添…

QT客户端外包开发的特点

QT是一种跨平台的C应用程序开发框架&#xff0c;主要用于开发图形用户界面(GUI)应用程序。它提供了一套丰富的类库和工具&#xff0c;可以帮助开发者快速构建高质量、可扩展、易于维护的应用程序。今天和大家分享一下QT的主要特点和注意的问题&#xff0c;希望对大家有所帮助。…

探索LeetCode【0011】盛最多水的容器(已懂)

目录 0. 题目1. 官方解答一&#xff08;已懂&#xff09;2. 精简解答二&#xff08;已懂&#xff09;3. 正确性解释 0. 题目 题目链接&#xff1a;【0011】盛最多水的容器 给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i,…

From Java To Kotlin:空安全、扩展、函数、Lambda很详细,这次终于懂了

From Java To Kotlin, 空安全、扩展、函数、Lambda 概述&#xff08;Summarize&#xff09; Kotlin 是什么&#xff1f;可以做什么&#xff1f;Android 官方开发语言从Java变为Kotlin,Java 有哪些问题&#xff1f;Kotlin的优点Kotlin 特性&#xff08;Features&#xff09; K…

有名的国外CRM系统有哪些?如何选择?

CRM系统可以帮助企业获得更多地潜在客户&#xff0c;优化销售流程&#xff0c;提高工作效率&#xff0c;增强客户服务水平&#xff0c;是如今企业不可或缺的工具。那么&#xff0c;国外CRM的知名厂商有哪些&#xff1f;下面小编来为大家进行推荐。 Zoho CRM&#xff1a; Zoho…

快手国际化 后端开发面经一面

目录 1.JMM内存模型2.堆怎么管理内存3.垃圾回收算法4.跨代引用问题怎么解决5.垃圾回收器6.CMS回收过程7.G1和CMS区别 1.JMM内存模型 计算机存储结构&#xff0c;从本地磁盘到主存到CPU缓存&#xff0c;也就是从硬盘到内存&#xff0c;到CPU。 问题&#xff1f;和推导出我们需要…

全国节能宣传周知识答题活动

全国节能宣传周知识答题活动 若想在短期内&#xff0c;进行安全生产知识的传播&#xff0c;那么答题无疑是有效方式之一。 答题活动小程序v3.0&#xff0c;基于微信原生小程序云开发实现。主要包含六大功能模块页面&#xff0c;首页、活动规则页、排行榜页、答题页、结果页、…

每日一个MySQL问题: MTS 高并发下主从表空间不一致的问题

简单记录原因&#xff0c;最近我也遇到这样的问题&#xff0c;涉及的知识点其实很多&#xff0c;我也仅仅是简单分析了一下&#xff0c;供参考。模拟版本8.0.28。 一、问题说明和模拟方式 就是主从一个表&#xff0c;主库大约600M&#xff0c;从库大约900M&#xff0c;当然主从…

推荐一个网络安全网站(HTML)

废话不多&#xff0c;直接上链接https://www.hackthissite.org/ 这不是一个新手向的网站&#xff0c;建议有一定基础的同学访问&#xff0c;里面大部分都是黑客实操&#xff0c;对大部分希望学习网络安全并有一定基础的人都可以有较大提升 全区英文&#xff0c;这对各位应该不…

Java面试题汇总(包含算法题及底层知识)

花了很久时间整理了Java领域互联网公司常考的面试题&#xff0c;主要包含六大类: 第一类:Java及Javaweb常考基础题及高级题&#xff0c;包含了很多公司爱问的非常冷门的知识点&#xff0c;很多面试官喜欢通过问非常冷门的知识来判断面试者的基础掌握程度。 第二类:Java虚拟机以…

EasyRecovery16电脑硬盘数据恢复软件功能讲解

硬盘是很常见的存储数据的设备&#xff0c;硬盘中很多重要的数据一旦丢失会很麻烦&#xff0c;不过现在有硬盘数据恢复软件可以自行在家恢复数据。今天的文章就带大家来看看硬盘恢复数据的软件EasyRecovery。 EasyRecovery 是一款专业的数据恢复软件&#xff0c;支持恢复不同存…

【Proteus仿真】51单片机Blink点灯实验

【Proteus仿真】51单片机Blink点灯实验 &#x1f516;Proteus仿真基础实验-点亮第一个LED灯。&#x1f33f;Proteus8.12平台&#x1f33f;本实验代码基于VSM Studio&#xff0c;采用SDCC编译器。&#x1f3ac;仿真演示&#xff1a; ⛳头文件使用说明 ⚡第一次调用STC89.h头文…

MySQL is null 走不走索引?

网上很多的说法&#xff0c;都是说不能走索引。但其实是错误的。 其实也是又可能走索引的。 比如&#xff0c;select * from table where a xxx or a is null; 通过explain 看这条sql的执行计划&#xff0c;type ref_or_null&#xff0c;这条sql语句会查询两次&#xff0c;第…