OpenCV计算机视觉整理图像、视频加载与显示OpenCV的色彩空间OpenCV图形绘制

图像、视频加载与显示

创建显示窗口

代码语言:javascript
复制
import cv2

if name == "main":

# 创建窗口
cv2.namedWindow('new', cv2.WINDOW_NORMAL)
# 调整窗口大小
cv2.resizeWindow('new', 640, 480)
# 显示窗口
cv2.imshow('new', 0)
# 显示时长
key = cv2.waitKey(0)
if key == 'q':
    exit()
# 销毁窗口
cv2.destroyWindow()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367931623613574.png" /></div></div></div></figure><p><strong>载入图片</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/WechatIMG12.jpeg&#34;)
cv2.imshow(&#39;img&#39;, img)
while True:
    key = cv2.waitKey(0)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367931771549030.png" /></div></div></div></figure><p><strong>保存文件</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/WechatIMG12.jpeg&#34;)
cv2.imshow(&#39;img&#39;, img)
while True:
    key = cv2.waitKey(0)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
    elif key &amp; 0xFF == ord(&#39;s&#39;):
        cv2.imwrite(&#34;/Users/admin/Documents/帅照.png&#34;, img)
cv2.destroyAllWindows()</code></pre></div></div><p>当我们点击键盘&#34;s&#34;键的时候,运行结果</p><p>进入/Users/admin/Documents文件夹</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">(base) -bash-3.2$ ls | grep 帅照

帅照.png

摄像头视频采集

代码语言:javascript
复制
import cv2

if name == "main":

# 创建窗口
cv2.namedWindow(&#39;video&#39;, cv2.WINDOW_NORMAL)
cv2.resizeWindow(&#39;video&#39;, 640, 480)
# 获取视频设备
cap = cv2.VideoCapture(0)
while True:
    # 从摄像头读视频桢
    ret, frame = cap.read()
    # 将视频帧在窗口中显示
    cv2.imshow(&#39;video&#39;, frame)
    key = cv2.waitKey(1)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
# 释放资源
cap.release()
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367933301345041.png" /></div></div></div></figure><p>这里可以看到摄像头已经打开,并开始采集视频。</p><p><strong>读取视频文件</strong></p><p>我们这里使用一段鹦鹉的视频,使用命令ffplay查看每秒播放帧数</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">./ffplay cockatoo.mp4

ffplay version N-104454-gd92fdc7144-tessus https://evermeet.cx/ffmpeg/ Copyright (c) 2003-2021 the FFmpeg developers
built with Apple clang version 11.0.0 (clang-1100.0.33.17)
configuration: --cc=/usr/bin/clang --prefix=/opt/ffmpeg --extra-version=tessus --enable-avisynth --enable-fontconfig --enable-gpl --enable-libaom --enable-libass --enable-libbluray --enable-libdav1d --enable-libfreetype --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libmysofa --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenh264 --enable-libopenjpeg --enable-libopus --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvmaf --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-libzimg --enable-libzmq --enable-libzvbi --enable-version3 --pkg-config-flags=--static --enable-librtmp --enable-ffplay --enable-sdl2 --disable-ffmpeg --disable-ffprobe
libavutil 57. 7.100 / 57. 7.100
libavcodec 59. 12.100 / 59. 12.100
libavformat 59. 8.100 / 59. 8.100
libavdevice 59. 0.101 / 59. 0.101
libavfilter 8. 16.100 / 8. 16.100
libswscale 6. 1.100 / 6. 1.100
libswresample 4. 0.100 / 4. 0.100
libpostproc 56. 0.100 / 56. 0.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'cockatoo.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf56.4.101
Duration: 00:00:14.00, start: 0.000000, bitrate: 416 kb/s
Stream #0:00x1: Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p(progressive), 1280x720, 387 kb/s, 20 fps, 20 tbr, 10240 tbn (default)
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:10x2: Audio: mp3 (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 24 kb/s (default)
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
13.63 A-V: -0.031 fd= 0 aq= 0KB vq= 0KB sq= 0B f=0/0

我们可以看到有这么一段

代码语言:javascript
复制
Stream #0:00x1: Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p(progressive), 1280x720, 387 kb/s, 20 fps, 20 tbr, 10240 tbn (default)

这里有一个20 fps,说明该视频是每秒播放20桢

代码语言:javascript
复制
import cv2

if name == "main":

# 创建窗口
cv2.namedWindow(&#39;video&#39;, cv2.WINDOW_NORMAL)
cv2.resizeWindow(&#39;video&#39;, 640, 480)
# 获取视频文件
cap = cv2.VideoCapture(&#34;/Users/admin/Downloads/cockatoo.mp4&#34;)
while True:
    # 从文件读视频桢
    ret, frame = cap.read()
    # 将视频帧在窗口中显示
    cv2.imshow(&#39;video&#39;, frame)
    # 此处不能设为1,否则会过快,可以设的比播放视频每秒帧数长一点
    key = cv2.waitKey(40)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
# 释放资源
cap.release()
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367934412681749.png" /></div></div></div></figure><p><strong>摄像头采集数据输出为媒体文件</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

fourcc = cv2.VideoWriter_fourcc(*&#39;MJPG&#39;)
# 25为帧率,(1280, 720)为分辨率,该分辨率必须与设备摄像头分辨率保持一致
vw = cv2.VideoWriter(&#34;/Users/admin/Documents/out.mp4&#34;, fourcc, 25, (1280, 720))
# 创建窗口
cv2.namedWindow(&#39;video&#39;, cv2.WINDOW_NORMAL)
cv2.resizeWindow(&#39;video&#39;, 640, 480)
# 获取摄像头资源
cap = cv2.VideoCapture(0)
# 判断摄像头是否打开
while cap.isOpened():
    # 从摄像头读视频桢
    ret, frame = cap.read()
    if ret:
        # 将视频帧在窗口中显示
        cv2.imshow(&#39;video&#39;, frame)
        # 写数据到多媒体文件
        vw.write(frame)
        key = cv2.waitKey(1)
        if key &amp; 0xFF == ord(&#39;q&#39;):
            break
    else:
        break
# 释放资源
cap.release()
vw.release()
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">(base) -bash-3.2$ ls | grep out

out.mp4

控制鼠标

代码语言:javascript
复制
import cv2
import numpy as np

def mouse_callback(event, x, y, flags, userdata):
print(event, x, y, flags, userdata)

if name == "main":

cv2.namedWindow(&#39;mouse&#39;, cv2.WINDOW_NORMAL)
cv2.resizeWindow(&#39;mouse&#39;, 640, 360)
# 设置鼠标回调
cv2.setMouseCallback(&#39;mouse&#39;, mouse_callback, &#39;123&#39;)
# 设置背景为黑色
img = np.zeros((360, 640, 3), np.uint8)
while True:
    cv2.imshow(&#39;mouse&#39;, img)
    key = cv2.waitKey(1)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367935190965353.png" /></div></div></div></figure><p>当鼠标在黑色区域滑动的时候,控制台会将鼠标的坐标给打印出来</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">0 272 156 0 123

0 272 155 0 123
0 272 155 0 123
0 271 155 0 123
0 271 155 0 123

TrackBar的使用

TrackBar就是一种滑动条,滑动到不同的位置,获取相应的值做不同的处理。

代码语言:javascript
复制
import cv2
import numpy as np

def callback():
pass

if name == "main":

cv2.namedWindow(&#39;trackbar&#39;, cv2.WINDOW_NORMAL)
# 创建trackbar,R是trackbar的名字,0是默认当前值,255是最大值
cv2.createTrackbar(&#39;R&#39;, &#39;trackbar&#39;, 0, 255, callback)
cv2.createTrackbar(&#39;G&#39;, &#39;trackbar&#39;, 0, 255, callback)
cv2.createTrackbar(&#39;B&#39;, &#39;trackbar&#39;, 0, 255, callback)
# 纯黑色背景
img = np.zeros((480, 640, 3), np.uint8)
while True:
    cv2.imshow(&#39;trackbar&#39;, img)
    r = cv2.getTrackbarPos(&#39;R&#39;, &#39;trackbar&#39;)
    g = cv2.getTrackbarPos(&#39;G&#39;, &#39;trackbar&#39;)
    b = cv2.getTrackbarPos(&#39;B&#39;, &#39;trackbar&#39;)
    img[:] = [b, g, r]
    key = cv2.waitKey(10)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367936047290775.png" /></div></div></div></figure><p>trackbar取不同的值会有不同的背景色</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367936363624007.png" /></div></div></div></figure><h2 id="39367" name="OpenCV%E7%9A%84%E8%89%B2%E5%BD%A9%E7%A9%BA%E9%97%B4"><strong>OpenCV的色彩空间</strong></h2><p><strong>RGB人眼的色彩空间</strong></p><p>每一个像素有三种颜色——红色、绿色和蓝色。通过不同光源的组合,形成真彩色,有暗的,有明亮的。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367936863611491.png" /></div></div></div></figure><p>上图中每一个方格都代表一个像素。</p><p>OpenCV默认使用的是BGR,BGR跟RGB的区别就是排列顺序的不同。电脑上一般的排列顺序都是RGB。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367938040482487.png" /></div></div></div></figure><p><strong>HSV/HSB/HSL</strong></p><p>HSV代表的是色相、饱和度、明亮度。HSB和HSV是一个意思。</p><ol class="ol-level-0"><li>Hue:色相,即色彩,如红色、蓝色</li><li>Saturation:饱和度,颜色的纯度,值越大,纯度越高,最开始的时候是灰的,逐渐增大就纯度越高,如果是红色就是纯红,蓝色就是纯蓝</li><li>Value:明度,代表更暗一些还是更亮一些,当更暗的时候,黑色的程度越高;更亮一些就黑色成分少一些。</li></ol><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367938979582909.png" /></div></div></div></figure><p>该图中旋转一圈的过程中代表了不同的颜色。对于饱和度来说,以中心点为基础,底下是黑色,上面是白色,中间是黑与白之间的灰。越靠近于圆柱边缘的地方,颜色的纯度越高。而对于纵轴,底下是黑色的,越往上越来越亮,这个就是明亮度。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367939824974941.png" /></div></div></div></figure><p>对于OpenCV来说更喜欢使用HSV,使用HSV在背景判断上要好过RGB,因为在一个背景中可能有各种绿色,使用HSV就可以统一将背景判断为绿色,而使用RGB就不太好判断,每一种成分都有。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367940670640219.png" /></div></div></div></figure><p>判断背景是通过色度来进行判断的,上图中0度就是纯红,60度就是黄色,120度为绿色,180度为青色,240度为蓝色,300度为粉红。这里是不考虑从圆心到边缘的渐变的一些因素的。</p><p><strong>HSL</strong></p><ol class="ol-level-0"><li>Hue:色相,即色彩,如红色、蓝色</li><li>Saturation:饱和度</li><li>Ligthness:亮度</li></ol><p>HSL与HSV看起来差不多,但存在着不同。</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367941304550528.png" /></div></div></div></figure><p>这里左图是HSL的,右图是HSV的,对于HSL到最顶成的时候就是纯白,无论色相是什么,饱和度是什么。而HSV就没有这么夸张。我们基本上使用的都是HSV,HSL几乎是不使用的。</p><p><strong>YUV</strong></p><p>YUV主要用在视频领域。Y代表的是灰色图像,UV代表的是颜色。YUV来自于电视节目,以前的电视只有黑白电视,就只有这个Y,后来有了彩色电视,但是要兼容黑白电视剧,当彩色电视机播放黑白电视剧的时候就只播放这个Y。一般的YUV包含YUV4:2:0、YUV4:2:2、YUV4:4:4。</p><p>YUV4:2:0</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367942249332287.png" /></div></div></div></figure><p>上图中,4个Y对应2个U或者V。不同的间隔,U或者V都是不一定的。</p><p><strong>色彩空间转换</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

def callback():
pass

if name == "main":

cv2.namedWindow(&#39;color&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
colorspaces = [cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA, cv2.COLOR_BGR2GRAY,
               cv2.COLOR_BGR2HSV_FULL, cv2.COLOR_BGR2YUV]
cv2.createTrackbar(&#39;curcolor&#39;, &#39;color&#39;, 0, len(colorspaces) - 1, callback)
while True:
    index = cv2.getTrackbarPos(&#39;curcolor&#39;, &#39;color&#39;)
    # 颜色空间转换
    cvt_img = cv2.cvtColor(img, colorspaces[index])
    cv2.imshow(&#39;color&#39;, cvt_img)
    key = cv2.waitKey(10)
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><p>trackbar取值为0的时候</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367942992852786.png" /></div></div></div></figure><p>trackbar取值为1的时候</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367946105889935.png" /></div></div></div></figure><p>trackbar取值为2的时候</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367947054494520.png" /></div></div></div></figure><p>trackbar取值为3的时候</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367947876950575.png" /></div></div></div></figure><p>trackbar取值为4的时候</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367949452208170.png" /></div></div></div></figure><p><strong>ROI(Region of Image)</strong></p><p>roi的意思是对图像的一个区域进行提取</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;roi&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
print(img.shape)
roi = img[0:550, 750:1350]
while True:
    # 颜色空间转换
    cv2.imshow(&#39;roi&#39;, roi)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">(1080, 1920, 3)</code></pre></div></div><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367950724785134.png" /></div></div></div></figure><p>我们这里需要注意的是img是一个numpy三维矩阵,它的第一个维度是图像的高,第二个维度是图像的宽,第三个维度是图像的通道数。</p><p><strong>Mat</strong></p><p>Mat就是矩阵,它的结构如下</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367951396347255.png" /></div></div></div></figure><p>对于Header头部来说,存放的是一些属性,包括维度、行数,列数。而Data是存放数据的地方,就是图像中的实际像素。总体如下</p><div class="table-wrapper"><table><thead><tr><th style="text-align:left"><div><div class="table-header"><p>字段</p></div></div></th><th style="text-align:left"><div><div class="table-header"><p>说明</p></div></div></th><th style="text-align:left"><div><div class="table-header"><p>字段</p></div></div></th><th style="text-align:left"><div><div class="table-header"><p>说明</p></div></div></th></tr></thead><tbody><tr><td style="text-align:left"><div><div class="table-cell"><p>dims</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>维度</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>channels</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>通道数 RGB是3</p></div></div></td></tr><tr><td style="text-align:left"><div><div class="table-cell"><p>rows</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>行数</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>size</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>矩阵大小</p></div></div></td></tr><tr><td style="text-align:left"><div><div class="table-cell"><p>cols</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>列数</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>type</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>dep+dt+chs CV_8UC3</p></div></div></td></tr><tr><td style="text-align:left"><div><div class="table-cell"><p>depth</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>像素的位深</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>data</p></div></div></td><td style="text-align:left"><div><div class="table-cell"><p>存放数据</p></div></div></td></tr></tbody></table></div><p><strong>Mat拷贝</strong></p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367951834014435.png" /></div></div></div></figure><p>这里Mat A是第一个创建的Mat,Mat B是拷贝Mat A,这里我们可以看到Mat A和Mat B的Header是两部分,而Data是它们公用的,也就是说Mat A和Mat B的Header的指针指向的是同一块内存空间。所以当我们用Mat B来拷贝Mat A的时候,默认情况下属于浅拷贝。有关深浅拷贝的概念请参考浅析克隆 </p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img1&#39;, cv2.WINDOW_NORMAL)
cv2.namedWindow(&#39;img2&#39;, cv2.WINDOW_NORMAL)
img1 = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 浅拷贝
img2 = img1
# 将图像左上角变成红色小方块
img1[10:100, 10:100] = [0, 0, 255]
while True:
    cv2.imshow(&#39;img1&#39;, img1)
    cv2.imshow(&#39;img2&#39;, img2)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367952415440820.png" /></div></div></div></figure><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367953235385098.png" /></div></div></div></figure><p>上面的两张图是两个不同的窗口,它们的左上角都有一小块红色的方块,说明,这种拷贝方式属于浅拷贝。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img1&#39;, cv2.WINDOW_NORMAL)
cv2.namedWindow(&#39;img2&#39;, cv2.WINDOW_NORMAL)
img1 = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 深拷贝
img2 = img1.copy()
# 将图像左上角变成红色小方块
img1[10:100, 10:100] = [0, 0, 255]
while True:
    cv2.imshow(&#39;img1&#39;, img1)
    cv2.imshow(&#39;img2&#39;, img2)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367953981873765.png" /></div></div></div></figure><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367954314004631.png" /></div></div></div></figure><p>这里我们可以看到img2的左上角是没有红色小方块的,说明这是深拷贝。</p><p><strong>Mat的属性</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
print(img.shape)
# 图像占用内存空间数,高度*宽度*通道数
print(img.size)
# 图像中每个元素的位深
print(img.dtype)</code></pre></div></div><p>运行结果</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">(1080, 1920, 3)

6220800
uint8

这里我们可以看到每个元素的类型是uint8,说明它是一个无符号8位整型,是从0~255的范围。

通道的分割与合并

这里我们需要明白一个概念,任何的单通道图像都是灰色的,而任何彩色图像都必须是三通道的。

代码语言:javascript
复制
import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 分割图像的三个通道
b, g, r = cv2.split(img)
while True:
    cv2.imshow(&#39;img&#39;, b)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367955072565366.png" /></div></div></div></figure><p>那么我们显示的是蓝色通道,为什么是黑白的呢?其实要显示蓝色通道的图像依然要合并另外两个通道,即红色通道和绿色通道,只不过这两个通道我们需要设置成纯黑。</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

import numpy as np

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 分割图像的三个通道
b, g, r = cv2.split(img)
filt = np.zeros((1080, 1920), np.uint8)
# 合并三个通道,但只保留蓝色通道信息
imgnew = cv2.merge((b, filt, filt))
while True:
    cv2.imshow(&#39;img&#39;, imgnew)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367955921395223.png" /></div></div></div></figure><p>如果我们要一张纯蓝色的图片呢?</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

import numpy as np

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
filt = np.zeros((1080, 1920), np.uint8)
b = np.full((1080, 1920), 255, np.uint8)
# 合并三个通道,但只保留蓝色通道信息
imgnew = cv2.merge((b, filt, filt))
while True:
    cv2.imshow(&#39;img&#39;, imgnew)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367956684451942.png" /></div></div></div></figure><p>对比两张图片,我们可以看到,在纯蓝图片中,蓝色通道中的所有像素值都是255,而从111.jpeg中蓝色通道的矩阵应该就是各不相同的像素大小最终显示出来的效果。</p><h2 id="39503" name="OpenCV%E5%9B%BE%E5%BD%A2%E7%BB%98%E5%88%B6"><strong>OpenCV图形绘制</strong></h2><p><strong>画线</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,5为线宽
cv2.line(img, (750, 550), (1350, 550), (255, 255, 255), 5)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367957074237836.png" /></div></div></div></figure><p>现在我们来画一条斜线,并增加锯齿感</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367957698557934.png" /></div></div></div></figure><p><strong>在视频中画线</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;video&#39;, cv2.WINDOW_NORMAL)
cv2.resizeWindow(&#39;video&#39;, 640, 480)
# 获取视频文件
cap = cv2.VideoCapture(&#34;/Users/admin/Downloads/cockatoo.mp4&#34;)
while True:
    # 从文件读视频桢
    ret, frame = cap.read()
    if ret:
        cv2.line(frame, (0, 600), (1280, 600), (0, 0, 255), 5)
        # 将视频帧在窗口中显示
        cv2.imshow(&#39;video&#39;, frame)
        # 此处不能设为1,否则会过快,可以设的比播放视频每秒帧数长一点
        key = cv2.waitKey(40)
        if key &amp; 0xFF == ord(&#39;q&#39;):
            break
    else:
        key = cv2.waitKey(40)
        if key &amp; 0xFF == ord(&#39;q&#39;):
            break
# 释放资源
cap.release()
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367958616380105.png" /></div></div></div></figure><p><strong>画矩形</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), 8)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367959386035895.png" /></div></div></div></figure><p><strong>画实心矩形</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367960228975880.png" /></div></div></div></figure><p><strong>画圆</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,5为线宽,16的锯齿度数
cv2.circle(img, (1050, 275), 275, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367960967184314.png" /></div></div></div></figure><p><strong>画实心圆</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367961562994169.png" /></div></div></div></figure><p><strong>画椭圆</strong></p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 360是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 0, 0, 360, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367962167026383.png" /></div></div></div></figure><p>如果我们要绘制椭圆的下半部分</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 180是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 0, 0, 180, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367962869617717.png" /></div></div></div></figure><p>如果我们要绘制椭圆的上半部分</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 180是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 180, 0, 180, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367963632349309.png" /></div></div></div></figure><p>如果我们要绘制一些斜的椭圆</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 180是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 60, 0, 360, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367964519320718.png" /></div></div></div></figure><p>如果我们要绘制一个与第一个椭圆垂直的椭圆</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 180是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 90, 0, 360, (0, 0, 255), 5, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367965276350959.png" /></div></div></div></figure><p>如果我们要画一个实体扇形</p><div class="rno-markdown-code"><div class="rno-markdown-code-toolbar"><div class="rno-markdown-code-toolbar-info"><div class="rno-markdown-code-toolbar-item is-type"><span class="is-m-hidden">代码语言:</span>javascript</div></div><div class="rno-markdown-code-toolbar-opt"><div class="rno-markdown-code-toolbar-copy"><i class="icon-copy"></i><span class="is-m-hidden">复制</span></div></div></div><div class="developer-code-block"><pre class="prism-token token line-numbers language-javascript"><code class="language-javascript" style="margin-left:0">import cv2

if name == "main":

cv2.namedWindow(&#39;img&#39;, cv2.WINDOW_NORMAL)
img = cv2.imread(&#34;/Users/admin/Documents/111.jpeg&#34;)
# 画一条白线(750, 550)为起始点坐标,(1350, 550)为终止点坐标
# (255, 255, 255)为颜色,用三通道表示,8为线宽,
# 1为锯齿度,越小锯齿感越强,越大越平滑
# cv2.line(img, (759, 550), (1350, 900), (255, 255, 255), 8, 1)
# 画一个红框(750, 0)为起始点坐标,(1350, 550)为终止点坐标
# -1表示线宽无限大,即为实心
# cv2.rectangle(img, (750, 0), (1350, 550), (0, 0, 255), -1)
# 画一个红色的圆,(1050, 275)为圆心坐标,275为半径,-1为线宽无限大,即为实心,16的锯齿度数
# cv2.circle(img, (1050, 275), 275, (0, 0, 255), -1, 16)
# 画一个红色的椭圆,(1050, 275)为中心点坐标,(500, 275)为长宽的一半
# 第一个0为长方体角度起始值,第二个0为长方体角度终止值
# 180是椭圆的画线部分的度数
cv2.ellipse(img, (1050, 275), (500, 275), 120, 330, 360, (0, 0, 255), -1, 16)
while True:
    cv2.imshow(&#39;img&#39;, img)
    key = cv2.waitKey()
    if key &amp; 0xFF == ord(&#39;q&#39;):
        break
cv2.destroyAllWindows()</code></pre></div></div><p>运行结果</p><figure class=""><div class="rno-markdown-img-url" style="text-align:center"><div class="rno-markdown-img-url-inner" style="width:100%"><div style="width:100%"><img src="https://cdn.static.attains.cn/app/developer-bbs/upload/1723367965941160063.png" /></div></div></div></figure><p>画多边形</p>