OpenCV シャオバイ チョンチョン
参照: Opencv と Python を使用して、独自のオブジェクト検出ソフトウェアを構築します 。
参考動画の内容によると自作も可能ですが、動画は全て英語で、機械翻訳の字幕も正確ではないため、手順やコードのコメントをメモにして整理し、完全なプロジェクトもテキストの最後に添付されています。
モデルを初期化する
インポートされたモデル ライブラリは、80 個のオブジェクトを検出するようにトレーニングされています。
# 初始化模型
net = cv2.dnn.readNet("dnn_model/yolov4-tiny.weights",
"dnn_model/yolov4-tiny.cfg") # 导入模型
model = cv2.dnn_DetectionModel(net)
model.setInputParams(size=(320, 320), scale=1 / 255) # 压缩图片至DNN可处理的尺寸,尺寸越大检测效果越好,但处理速度会变慢
物体検出
# 物体检测
(class_ids, scores, bboxes) = model.detect(frame)
print("class ids", class_ids) # 分类结果
print("scores", scores) # 准确度
print("bboxes", bboxes) # 识别框的位置信息
画像ウィンドウに認識ボックスと結果を表示する
- 輸入認識分類表
# 将识别分类表赋值到classes
classes = []
with open("dnn_model/classes.txt", "r") as file_object: # 只读模式读取文件
for class_name in file_object.readlines(): # 将识别结果赋值到数组
class_name = class_name.strip() # 去掉头尾的空格或换行
classes.append(class_name) # 将class_name加入到classes里
- 認識ボックスとテキスト結果を表示するウィンドウ
# 在画面上显示识别框和识别结果
for class_id, score, bbox in zip(class_ids, scores, bboxes): # 将多帧数据打包重组成单帧
(x, y, w, h) = bbox # x,y代表识别框左上角位置坐标,w宽度,h高度
class_name = classes[class_id]
# 在画面上画出矩形框框住物体,用文本显示识别结果
cv2.rectangle(frame, (x, y), (x + w, y + h), (128, 42, 42), 3) # 画面,左上角坐标,右下角坐标,RGB颜色,厚度
cv2.putText(frame, class_name, (x, y - 10), cv2.FONT_HERSHEY_PLAIN, 2, (128, 42, 42), 2) # 画面,文本内容,位置,字体,字体大小,RGB颜色,厚度
カメラの解像度を変更する
これまでのところ、オブジェクトの検出は予備的に完了しています。処理速度と認識精度の関係を調整するには、カメラの解像度またはモデルのサイズを変更します。たとえば、カメラを初期化するコードにいくつかのセットアップ ステートメントを追加します。
# 初始化摄像头
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
インターフェイスを設計する
ビデオの弟は、インタラクティブ性を高める方法も教えてくれました.最終的な効果は、画面上のボタンをクリックしてオブジェクト検出結果を表示するかどうか、つまりオブジェクトをフレーミングするかどうかを制御することです.
自分でコードを書くことも、他の人が書いた関数を直接呼び出すこともできます。ここでは、自分で設計する方法のみを示します。
新しいウィンドウを作成し、マウス応答機能を追加します
# 定义鼠标响应回调函数
def click_button(event, x, y, flags, params):
if event == cv2.EVENT_LBUTTONDOWN:
print(x, y)
# 创建新窗口
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", click_button)
画面上にボタンアイコンを作成する
ここで、rectangle を fillPoly に置き換えると、データ処理を高速化できます. import numpy as np を使用する前に先頭に追加する必要があることに注意してください.
# 在画面上创建按钮
# cv2.rectangle(frame, (20, 20), (210, 70), (0, 0, 200), -1) # 边框厚度为-1表示用颜色填充这个框框
polygon = np.array([[(20, 20), (210, 20), (210, 70), (20, 70)]]) # 通过绘制多边形来创建按钮
cv2.fillPoly(frame, polygon, (0, 0, 200))
cv2.putText(frame, "Person", (30,60), cv2.FONT_HERSHEY_PLAIN, 3, (255, 255, 255), 3)
マウス応答関数を変更します
- pointPolygonTest 関数の使用: ポイントがポリゴン内にあるかどうかを検出するために使用されます
- パラメータの輪郭はポリゴンを表します
- 2 番目のパラメータ pt はテスト ポイントを表します
- 3 つのパラメーター measureDist ブール変数
measureDist が true に設定されている場合、実際の距離値を返します。
戻り値が正の場合はポイントがポリゴンの内側にあることを意味し、戻り値が負の場合はポリゴンの外側にあることを意味し、戻り値は 0 でポリゴン上にあることを意味します。
measureDist を false に設定すると、-1、0、1 の 3 つの固定値が返されます。
戻り値が +1 の場合はポイントがポリゴンの内側にあることを意味し、戻り値が -1 の場合はポリゴンの外側にあることを意味し、戻り値が 0 の場合はポリゴン上にあることを意味します。
button_person = False # 用以标志按钮状态
# 定义鼠标响应回调函数
def click_button(event, x, y, flags, params):
global button_person
if event == cv2.EVENT_LBUTTONDOWN:
print(x, y)
polygon = np.array([[(20, 20), (210, 20), (210, 70), (20, 70)]]) # 通过绘制多边形来创建按钮
is_inside = cv2.pointPolygonTest(polygon, (x, y), False)
if is_inside > 0:
print("按钮被点击")
# 改变按钮状态标志位
if button_person:
button_person = False
else:
button_person = True
print("按钮状态为", button_person)
条件判定を追加
ボタンのステータスフラグに応じて、認識ボックスと結果を表示するかどうかを決定する条件判断ステートメントを追加します。
if class_name == "person" and button_person is True:
# 在画面上画出矩形框框住物体,用文本显示识别结果
cv2.rectangle(frame, (x, y), (x + w, y + h), (128, 42, 42), 3) # 画面,左上角坐标,右下角坐标,RGB颜色,厚度
cv2.putText(frame, class_name, (x, y - 10), cv2.FONT_HERSHEY_PLAIN, 2, (128, 42, 42), 2) # 画面,文本内容,位置,字体,字体大小,RGB颜色,厚度
プロジェクトの完了
完全なプロジェクトのリンクはこちらのリンクです (設定値の要件はありません)。