《數(shù)字圖像處理-OpenCV/Python》連載(26)繪制橢圓和橢圓弧
本書京東優(yōu)惠購書鏈接:https://item.jd.com/14098452.html
本書CSDN獨(dú)家連載專欄:https://blog.csdn.net/youcans/category_12418787.html
第 4 章 繪圖與鼠標(biāo)交互
本章介紹OpenCV的繪圖功能和簡單的鼠標(biāo)交互處理方法。與Excel或Matplotlib中的可視化數(shù)據(jù)圖不同,OpenCV中的繪圖功能主要用于在圖像的指定位置繪制幾何圖形。
本章內(nèi)容概要
- 學(xué)習(xí)OpenCV繪圖的基本方法和參數(shù)。
- 通過學(xué)習(xí)OpenCV繪圖函數(shù),能在圖像上繪制直線、矩形、圓形和多邊形等,以及在圖像上添加文字和符號。
- 介紹鼠標(biāo)交互操作方法,通過鼠標(biāo)、鍵盤與顯示圖像的實(shí)時交互獲取數(shù)據(jù)。
4.5 繪制圓形和橢圓
4.5.2 繪制橢圓和橢圓弧
函數(shù)cv.ellipse用于在圖像上繪制橢圓輪廓、填充橢圓、橢圓弧或填充橢圓扇區(qū)。
函數(shù)原型
cv.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness=1, lineType=LINE_8, shift=0]) → img
cv.ellipse(img, box, color[, thickness=1, lineType=LINE_8]) → img
參數(shù)說明
- img:輸入/輸出圖像,允許為單通道灰度圖像或多通道彩色圖像。
- center:橢圓中心點(diǎn)的坐標(biāo),格式為元組(x,y)。
- axes:橢圓半軸長度,格式為元組 (hfirst,hsecond)。
- angle:橢圓沿x軸方向的旋轉(zhuǎn)角度(角度制,按順時針方向)。
- startAngle:繪制橢圓/圓弧的起始角度。
- endAngle:繪制橢圓/圓弧的終止角度。
- box:旋轉(zhuǎn)矩形類RotateRect,格式為元組((x,y),(w,h),angle)。
注意問題
- (1)橢圓參數(shù)的定義非常復(fù)雜,容易混淆,以下結(jié)合圖4-5所示的橢圓繪制參數(shù)示意圖來解釋。
- axes的值是橢圓主軸長度的一半,而不是主軸長度。第一半軸hfirst指x軸順時針旋轉(zhuǎn)時首先遇到的軸,與長軸或短軸無關(guān);第二半軸hsecond是與第一半軸垂直的軸。
- startAngle和endAngle都是指從第一半軸開始順時針旋轉(zhuǎn)的角度,起止角度與次序無關(guān)。(0,360)表示繪制整個橢圓,(0,180)表示繪制半個橢圓。
圖4-5 橢圓繪制參數(shù)示意圖
-
(2)box是旋轉(zhuǎn)矩形類RotatedRect,由box可確定一個內(nèi)接于box的橢圓。
- 旋轉(zhuǎn)矩形類RotatedRect在Python中是形狀為((x,y),(w,h),angle)的元組,(x,y)表示矩形中心點(diǎn)坐標(biāo),(w,h)表示矩形的寬和高、angle表示旋轉(zhuǎn)角度,范圍為[-180,180]。
-
(3) 函數(shù)cv.ellipse采用分段線性曲線逼近橢圓弧邊界。如果需要對橢圓進(jìn)行更多控制,可以使用ellipse2Poly檢索曲線后進(jìn)行渲染或填充。
【例程0405】繪制橢圓和橢圓弧
本例程用于繪制橢圓和橢圓弧,注意對照圖4-5理解各個參數(shù)的含義。
# 【0405】繪制橢圓和橢圓弧
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
if __name__ == '__main__':
img = np.ones((400, 600, 3), np.uint8)*224
img1 = img.copy()
img2 = img.copy()
# (1) 半軸長度 (haf) 的影響
cx, cy = 150, 200 # 圓心坐標(biāo)
angle = 120 # 旋轉(zhuǎn)角度
startAng, endAng = 0, 360 # 開始角度,結(jié)束角度
haf = [50, 100, 150, 180] # 第一軸的半軸長度
has = 100 # 第二軸的半軸長度
for i in range(len(haf)):
color = (i*50, i*50, 255-i*50)
cv.ellipse(img1, (cx,cy), (haf[i],has), angle, startAng, endAng, color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf[i]*np.cos(angPi))
ye = int(cy + haf[i]*np.sin(angPi))
cv.circle(img1, (xe,ye), 2, color, -1)
cv.arrowedLine(img1, (cx,cy), (xe,ye), color) # 從圓心指向第一軸端點(diǎn)
text = "haF={}".format(haf[i])
cv.putText(img1, text, (xe+5,ye), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
# 繪制第二軸
xe = int(cx + has*np.sin(angPi)) # 計算第二軸端點(diǎn)坐標(biāo)
ye = int(cy - has*np.cos(angPi))
cv.arrowedLine(img1, (cx, cy), (xe, ye), color) # 從圓心指向第二軸端點(diǎn)
text = "haS={}".format(has)
cv.putText(img1, text, (xe-80, ye+30), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
# (2) 旋轉(zhuǎn)角度 (angle) 的影響
cx, cy = 420, 180 # 圓心坐標(biāo)
haf, has = 120, 60 # 半軸長度
startAng, endAng = 0,360 # 開始角度,結(jié)束角度
angle = [0, 30, 60, 135] # 旋轉(zhuǎn)角度
for i in range(len(angle)):
color = (i*50, i*50, 255-i*50)
cv.ellipse(img1, (cx,cy), (haf,has), angle[i], startAng, endAng, color, 2)
angPi = angle[i] * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cy + haf*np.sin(angPi))
cv.circle(img1, (xe,ye), 2, color, -1)
cv.arrowedLine(img1, (cx,cy), (xe,ye), color) # 從圓心指向第一軸端點(diǎn)
text = "rot {}".format(angle[i])
cv.putText(img1, text, (xe+5,ye), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
# (3) 起始角度 (startAngle) 的影響 I
cx, cy = 60, 80 # 圓心坐標(biāo)
haf, has = 45, 30 # 半軸長度
angle = 0 # 旋轉(zhuǎn)角度
endAng = 360 # 結(jié)束角度
startAng = [0, 45, 90, 180] # 開始角度
for i in range(len(startAng)):
color = (i*20, i*20, 255-i*20)
cyi = cy+i*90
cv.ellipse(img2, (cx,cyi), (haf,has), angle, startAng[i], endAng, color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cyi + haf*np.sin(angPi))
cv.arrowedLine(img2, (cx,cyi), (xe,ye), 255) # 從圓心指向第一軸端點(diǎn)
text = "start {}".format(startAng[i])
cv.putText(img2, text, (cx-40,cyi), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "end={}".format(endAng)
cv.putText(img2, text, (10, cy-50), cv.FONT_HERSHEY_SIMPLEX, 0.6, 255)
# (4) 起始角度 (startAngle) 的影響 II
cx, cy = 180, 80 # 圓心坐標(biāo)
haf, has = 45, 30 # 半軸長度
angle = 30 # 旋轉(zhuǎn)角度
endAng = 360 # 結(jié)束角度
startAng = [0, 45, 90, 180] # 開始角度
for i in range(len(startAng)):
color = (i*20, i*20, 255-i*20)
cyi = cy+i*90
cv.ellipse(img2, (cx,cyi), (haf,has), angle, startAng[i], endAng, color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cyi + haf*np.sin(angPi))
cv.arrowedLine(img2, (cx,cyi), (xe,ye), 255) # 從圓心指向第一軸端點(diǎn)
text = "start {}".format(startAng[i])
cv.putText(img2, text, (cx-40,cyi), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "end={}".format(endAng)
cv.putText(img2, text, (150,cy-50), cv.FONT_HERSHEY_SIMPLEX, 0.6, 255)
# (5) 結(jié)束角度 (endAngle) 的影響 I
cx, cy = 300, 80 # 圓心坐標(biāo)
haf, has = 45, 30 # 半軸長度
angle = 0 # 旋轉(zhuǎn)角度
startAng = 0 # 開始角度
endAng = [45, 90, 180, 360] # 結(jié)束角度
for i in range(len(endAng)):
color = (i*20, i*20, 255-i*20)
cyi = cy+i*90
cv.ellipse(img2, (cx,cyi), (haf,has), angle, startAng, endAng[i], color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cyi + haf*np.sin(angPi))
cv.arrowedLine(img2, (cx,cyi), (xe,ye), 255) # 從圓心指向第一軸端點(diǎn)
text = "end {}".format(endAng[i])
cv.putText(img2, text, (cx-40,cyi), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "start={}".format(startAng)
cv.putText(img2, text, (250,cy-50), cv.FONT_HERSHEY_SIMPLEX, 0.6, 255)
# (6) 結(jié)束角度 (endAngle) 的影響 II
cx, cy = 420, 80 # 圓心坐標(biāo)
haf, has = 45, 30 # 半軸長度
angle = 30 # 旋轉(zhuǎn)角度
startAng = 45 # 開始角度
endAng = [30, 90, 180, 360] # 結(jié)束角度
for i in range(len(endAng)):
color = (i*20, i*20, 255-i*20)
cyi = cy+i*90
cv.ellipse(img2, (cx,cyi), (haf,has), angle, startAng, endAng[i], color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cyi + haf*np.sin(angPi))
cv.arrowedLine(img2, (cx,cyi), (xe,ye), 255) # 從圓心指向第一軸端點(diǎn)
text = "end {}".format(endAng[i])
cv.putText(img2, text, (cx-40,cyi), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "start={}".format(startAng)
cv.putText(img2, text, (370,cy-50), cv.FONT_HERSHEY_SIMPLEX, 0.6, 255)
# (7) 起始角度和結(jié)束角度的影響
cx, cy = 540, 80 # 圓心坐標(biāo)
haf, has = 40, 30 # 半軸長度
angle = 30 # 旋轉(zhuǎn)角度
startAng = [0, 0, 180, 180 ] # 開始角度
endAng = [90, 180, 270, 360] # 結(jié)束角度
for i in range(len(endAng)):
color = (i*20, i*20, 255-i*20)
cyi = cy+i*90
cv.ellipse(img2, (cx,cyi), (haf,has), angle, startAng[i], endAng[i], color, 2)
angPi = angle * np.pi / 180 # 轉(zhuǎn)換為弧度制,便于計算坐標(biāo)
xe = int(cx + haf*np.cos(angPi))
ye = int(cyi + haf*np.sin(angPi))
cv.arrowedLine(img2, (cx,cyi), (xe,ye), 255) # 從圓心指向第一軸端點(diǎn)
text = "start {}".format(startAng[i])
cv.putText(img2, text, (cx-40,cyi-20), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "end {}".format(endAng[i])
cv.putText(img2, text, (cx-40,cyi), cv.FONT_HERSHEY_SIMPLEX, 0.6, color)
text = "rotate={}".format(angle)
cv.putText(img2, text, (490,cy-50), cv.FONT_HERSHEY_SIMPLEX, 0.6, 255)
plt.figure(figsize=(9, 3.5))
plt.subplot(121), plt.title("1. Ellipse1"), plt.axis('off')
plt.imshow(cv.cvtColor(img1, cv.COLOR_BGR2RGB))
plt.subplot(122), plt.title("2. Ellipse2"), plt.axis('off')
plt.imshow(cv.cvtColor(img2, cv.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
程序說明:
運(yùn)行結(jié)果,繪制橢圓和橢圓弧如圖4-6所示。
(1)圖4-6(1)的左側(cè)圖形用于比較半軸長度的影響,表明第一半軸hfirst與長軸或短軸無關(guān),而是取決于橢圓的旋轉(zhuǎn)方向。
(2)圖4-6(1)的右側(cè)圖形用于比較旋轉(zhuǎn)角度的影響,旋轉(zhuǎn)角度是指沿x軸方向順時針旋轉(zhuǎn)的角度。
(3)起始角度和結(jié)束角度的定義及關(guān)系比較復(fù)雜,圖4-6(2)給出了詳細(xì)示例,請對照程序注釋與顯示圖像進(jìn)行比較和理解。
圖4-6 繪制橢圓和橢圓弧
版權(quán)聲明:
youcans@xupt 原創(chuàng)作品,轉(zhuǎn)載必須標(biāo)注原文鏈接:(https://blog.csdn.net/youcans/article/details/134014737)
Copyright 2023 youcans, XUPT
Crated:2023-10-24文章來源:http://www.zghlxwxcb.cn/news/detail-734586.html
歡迎關(guān)注本書CSDN獨(dú)家連載專欄
《數(shù)字圖像處理-OpenCV/Python》連載: https://blog.csdn.net/youcans/category_12418787.html文章來源地址http://www.zghlxwxcb.cn/news/detail-734586.html
到了這里,關(guān)于《數(shù)字圖像處理-OpenCV/Python》連載(26)繪制橢圓和橢圓弧的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!