番外5. Python OpenCV 中滑動條詳細說明與常見問題解决方案

夢想橡皮擦 2021-08-15 11:04:07 阅读数:99

本文一共[544]字,预计阅读时长:1分钟~
python opencv 解决方案 解决 方案

本系列專欄寫作方式

本系列專欄寫作將采用首創的問答式寫作形式,快速讓你學習到 OpenCV 的初級、中級、高級知識。

5. Python OpenCV 中滑動條詳細說明與常見問題解决方案

滑動條在 OpenCV 相關案例中使用場景非常豐富,很多時候都需要借助於滑動條進行相關參數的獲取。

掌握滑動條,只需要掌握 cv2.createTrackbarcv2.getTrackbarPos 兩個函數即可。

以上兩個函數的原型,可以直接通過 help 函數查閱,本系列專欄對於函數原型只做簡單說明

createTrackbar(trackbarName, windowName, value, count, onChange) -> None
getTrackbarPos(trackbarname, winname) -> retval

其中 cv2.createTrackbar 函數參數豐富一些,cv2.getTrackbarPos 函數是其子級。

接下來通過一個簡單的案例,實現滑動條的基本應用,拖動改變窗口中某矩形的顏色。

import cv2
import numpy as np
cv2.namedWindow("Trackbar_Demo", cv2.WINDOW_NORMAL)
# 為了在滑動條中參數比特置進行占比特
def nothing():
pass
ret = np.zeros([512, 512, 3], np.uint8)
# 創建一個滑動條
cv2.createTrackbar("color_green", "Trackbar_Demo", 0, 255, nothing)
while 1:
# 獲取滑動條的取值
color_green = cv2.getTrackbarPos("color_green", "Trackbar_Demo")
cv2.rectangle(ret, (100, 100), (200, 200), (0, color_green, 0), -1)
cv2.imshow("Trackbar_Demo", ret)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()

如果在代碼編寫過程中出現了如下 BUG,缺少參數:

TypeError: function takes exactly 5 arguments (4 given)

該 BUG 錶示 cv2.createTrackbar 函數中缺少了最後一個 onChange 參數,添加該參數即可,參數指向的函數體可以為空。

代碼運行之後的動圖效果如下:

cv2.createTrackbar 函數中 onChange 參數相關問題解决方案

在互聯網上所有的中文資料中進行檢索,會發現有一個知識點在 cv2.createTrackbar 函數的應用中經常被忽略,這個內容就是 onChange 參數,該參數的官方說明如下:

Pointer to the function to be called every time the slider changes position. This function should be prototyped as void Foo(int,void*); , where the first parameter is the trackbar position and the second parameter is the user data (see the next parameter). If the callback is the NULL pointer, no callbacks are called, but only value is updated.

這裏要注意一個細節的地方,在 OpenCV C++ 編寫的時候,這個函數裏面多一個參數,叫做 userdata ,也就是說 C++ 中此函數的原型如下:

int createTrackbar(const String& trackbarname, const String& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)

但是 Python 對其進行了整合,通過一個參數完成兩個數據值的操作,這樣其實我們在進行每一次拖動滑動條的時候,都可以對其進行相應的操作。

修改代碼如下,篇幅關系,只修改 nothing 函數部分,運行代碼會出現下圖所示內容:

# 滑動條每步的回調函數
def nothing(x):
print("滑動條進行操作")
print(x)

甚至我可以直接調整代碼邏輯,將繪制矩形的操作放到滾動條的回調函數中,具體代碼與說明如下:

import cv2
import numpy as np
cv2.namedWindow("Trackbar_Demo", cv2.WINDOW_NORMAL)
# 滑動條每步的回調函數
def nothing(x):
print("滑動條進行操作")
cv2.rectangle(ret, (100, 100), (200, 200), (0, x, 0), -1)
ret = np.zeros([512, 512, 3], np.uint8)
# 創建一個滑動條
cv2.createTrackbar("color_green", "Trackbar_Demo", 0, 255, nothing)
# color_green = cv2.getTrackbarPos("color_green", "Trackbar_Demo")
while True:
cv2.imshow("Trackbar_Demo", ret)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()

這種邏輯具備之後,我們就可以將滑動條設計成一個開關,拖動到不同值,可以呈現不同的效果。

更多細節,可以繼續取閱讀手册相關內容,訪問地址

OpenCV 中拆分滑動條與圖片窗口

在實際編碼過程中,建議將滑動條窗口與圖片窗口進行拆分展示,便於調整各參數。

例如下面一個手動調參實現二值化的操作(後續文章會涉及到)。

import cv2
import numpy as np
def nothing(a):
pass
cv2.namedWindow("HSV",cv2.WINDOW_AUTOSIZE)
cv2.createTrackbar("HUE Min", "HSV", 0, 255, nothing)
cv2.createTrackbar("HUE Max", "HSV", 180, 255, nothing)
cv2.createTrackbar("SAT Min", "HSV", 255, 255, nothing)
cv2.createTrackbar("SAT Max", "HSV", 43, 255, nothing)
cv2.createTrackbar("VALUE Min", "HSV", 255, 255, nothing)
cv2.createTrackbar("VALUE Max", "HSV", 46, 255, nothing)
while True:
img = cv2.imread("./t1.jpg")
imgHsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h_min = cv2.getTrackbarPos("HUE Min", "HSV")
h_max = cv2.getTrackbarPos("HUE Max", "HSV")
s_min = cv2.getTrackbarPos("SAT Min", "HSV")
s_max = cv2.getTrackbarPos("SAT Max", "HSV")
v_min = cv2.getTrackbarPos("VALUE Min", "HSV")
v_max = cv2.getTrackbarPos("VALUE Max", "HSV")
lower = np.array([h_min, s_min, v_min])
upper = np.array([h_max, s_max, v_max])
mask = cv2.inRange(imgHsv, lower, upper)
result = cv2.bitwise_and(img, img, mask=mask)
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
hStack = np.hstack([img, mask, result])
cv2.imshow('Horizontal Stacking', hStack)
if cv2.waitKey(1) & 0xFF == 27:
break
cv2.destroyAllWindows()

以上代碼運行之後,會呈現一種非常便捷的操作,拖動一個窗口,在另一個窗口中可以動態的呈現對應變化。

這個地方編碼的時候有一個注意事項,即 cv2.namedWindow(“HSV”, cv2.WINDOW_AUTOSIZE) 函數部分,請使用 cv2.WINDOW_AUTOSIZE 值,如果不使用該值,很容易造成滑動條窗口亂版的情况,或者窗口參數分布不均勻情况。

最後再次强調滑動條的另一個作用,轉換按鈕。畢竟在 OpenCV 中不存在按鈕函數,使用帶有固定值的滑動條可以有效的解决該問題。

使用代碼如下所示即可:

cv2.createTrackbar(switch,'image',0,1,nothing)
果不使用該值,很容易造成滑動條窗口亂版的情况,或者窗口參數分布不均勻情况。
最後再次强調滑動條的另一個作用,轉換按鈕。畢竟在 OpenCV 中不存在按鈕函數,使用帶有固定值的滑動條可以有效的解决該問題。
使用代碼如下所示即可:
```python
cv2.createTrackbar(switch,'image',0,1,nothing)
版权声明:本文为[夢想橡皮擦]所创,转载请带上原文链接,感谢。 https://gsmany.com/2021/08/20210815110352259f.html