計算機視覺:圖像分類定位(單一目標檢測)python實現

前言

目標檢測:咱們不只要用算法判斷圖片中是否是貓仍是狗, 還要在圖片中標記出它的位置, 用邊框或紅色方框把貓狗圈起來, 這就是目標檢測問題。其中「定位」的意思是判斷貓狗在圖片中的具體位置。python

目標檢測有兩類任務:單一目標 ,多目標。算法

能力差,電氣專業,又未怎麼深刻研究cv.
因此本文先探討單一目標。
在這裏插入圖片描述

數組

HOG+SVM實現行人檢測

先講解 opencv自帶的行人檢測例子
HOG原理見
計算機視覺:圖像特徵與描述大全 ,有代碼(一篇博文帶你簡單瞭解完圖像特徵提取技術)

app

很少說,上代碼機器學習

import cv2 as cv

# 讀取圖像
src = cv.imread("duoren.jpg")
cv.imshow("input", src)
# HOG + SVM
hog = cv.HOGDescriptor()
hog.setSVMDetector(cv.HOGDescriptor_getDefaultPeopleDetector())
# Detect people in the image
(rects, weights) = hog.detectMultiScale(src,winStride=(4, 4), padding=(8, 8),scale=1.25,useMeanshiftGrouping=False)
# 矩形框
for (x, y, w, h) in rects:
    cv.rectangle(src, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 顯示[添加連接描述](https://blog.csdn.net/kobeyu652453/article/details/107382227)
cv.imshow("result", src)
cv.waitKey(0)
cv.destroyAllWindows()

圖像定位實現

python +keras實現圖像分類(入門級例子講解)
opencv進階學習筆記12:輪廓發現和對象測量
ide

目標檢測算法很複雜。
我嘗試用 圖像分類+對象測量 來實現單目標的圖像檢測。
函數

圖像分類 對象測量 很少說了,參考上面給的連接。學習

1讀取圖片並去噪ui

import cv2 as cv

image= cv.imread("catdog/dog/dog.77.jpg")
image=cv.resize(image,None,fx=0.5,fy=0.5)
blurred = cv.GaussianBlur(image, (5, 5), 0)  # 去噪

2二值化圖像spa

gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)

3繪製輪廓邊緣

contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

cv2.findContours()函數第一個參數是要檢索的圖片,必須是爲二值圖,即黑白的(不是灰度圖),因此讀取的圖像要先轉成灰度的,再轉成二值圖,
參數講解
contours,hierarchy=cv2.findContours(image,mode,method)
contours:輪廓
hierarchy:圖像的拓撲信息(輪廓層次)(存儲上一個輪廓,父輪廓…)
image:二值圖像
mode:輪廓檢索方式
method:輪廓的近似方法






4求得包含點集最小面積的矩形,這個矩形是能夠有偏轉角度的,能夠與圖像的邊界不平行。

c = sorted(contours, key=cv.contourArea, reverse=True)[0]

rect = cv.minAreaRect(c)
box = np.int0( cv.boxPoints(rect))

# draw a bounding box arounded the detected barcode and display the image
cv.drawContours(image, [box], -1, (0, 255, 0), 3)

講解

double cvContourArea( const CvArr* contour, CvSlice slice=CV_WHOLE_SEQ );
contour:輪廓(頂點的序列或數組)。
slice:感興趣區輪廓部分的起點和終點,默認計算整個輪廓的面積。

c = sorted(contours, key=cv.contourArea, reverse=True)[0]
取出最大的輪廓面積,有些輪廓爲噪聲。
最大輪廓通常狀況下能取到咱們想要的目標物。

minAreaRect函數返回矩形的中心點座標,長寬,旋轉角度[-90,0),當矩形水平或豎直時均返回-90

使用cv2.boxPoints()可獲取該矩形的四個頂點座標。 浮點型數據

np.int0 取整

r=cv2.drawContours(image, contours, contourIdx, color[, thickness])
r:目標圖像
image:原始圖像
contours: 全部的輸入輪廓邊緣數組
contourIdx :須要繪製的邊緣索引,若是所有繪製爲-1。若是有多個目標,能夠繪製第一個目標0,第二個目標1,第三個目標2.。。
color:繪製的顏色,爲BGR格式的SCalar
thickness:可選,繪製的密度,即輪廓的畫筆粗細





5找出四個頂點的x,y座標的最大最小值。矩形框的高=maxY-minY,寬=maxX-minX。

因爲前面的提到的 包含點集最小面積的矩形 有的矩形不與圖像平行,是斜着的,以下圖。咱們調整矩形框。

Xs = [i[0] for i in box]
    Ys = [i[1] for i in box]
    x1 = min(Xs)
    x2 = max(Xs)
    y1 = min(Ys)
    y2 = max(Ys)
    hight = y2 - y1
    width = x2 - x1
    cropImg = image[y1:y1 + hight, x1:x1 + width]
    cv.rectangle(image, (x1, y1), (x1 + width, y1 +hight ), (0, 0, 255), 2)  # 在原圖上,給輪廓繪製矩形
    cv.imshow('result',image)

全部代碼

import cv2 as cv
import numpy as np
src= cv.imread("dog.16.jpg")
src=cv.resize(src,None,fx=0.5,fy=0.5)
image=src.copy()
#去噪
blurred = cv.GaussianBlur(image, (5, 5), 0)  # 去噪
#灰度轉換
gray = cv.cvtColor(blurred, cv.COLOR_BGR2GRAY)
#二值化
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
#輪廓發現
contours, hireachy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
#取出最大輪廓
c = sorted(contours, key=cv.contourArea, reverse=True)[0]
#找到最大輪廓的最小外接矩形
rect = cv.minAreaRect(c)
#取出最小外接矩形的四個頂點
box = np.int0( cv.boxPoints(rect))
#繪製矩形框
Xs = [i[0] for i in box]
Ys = [i[1] for i in box]
x1 = min(Xs)
x2 = max(Xs)
y1 = min(Ys)
y2 = max(Ys)
hight = y2 - y1
width = x2 - x1
cropImg = image[y1:y1 + hight, x1:x1 + width]
cv.rectangle(image, (x1, y1), (x1 + width, y1 + hight), (0, 0, 255), 2)  # 在原圖上,給輪廓繪製矩形
#顯示
cv.imshow("input image", src)
cv.imshow('result', image)

cv.waitKey(0)
cv.destroyAllWindows()

圖像分類定位實現

我應用圖像分類 加前面提到的定位 結合起來作 單目標的圖像監測。

圖像分類前面給出了連接,這裏再也不給啦,博文太多連接了,會被顯示待審覈。

PYQT 封裝吧。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu
# @Date : 2020/8/1
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

import cv2
import keras
from keras .models import load_model
import numpy as np
import re
class picture(QWidget):
    def __init__(self):
        super(picture, self).__init__()

        self.resize(600, 400)
        self.setWindowTitle("貓狗分類")
        self.btn = QPushButton()
        self.btn.setText("打開圖片")
        self.btn.clicked.connect(self.openimage)
        self.label = QLabel()
        self.label.setText('圖片路徑')


        self.labelimage = QLabel()
        self.labelimage.setText("顯示圖片")
        #self.labelimage.setFixedSize(500, 400)#設置尺寸
        self.labelimage.setStyleSheet("QLabel{background:white;}"
                                 "QLabel{color:rgb(300,300,300,120);font-size:10px;font-weight:bold;font-family:宋體;}"
                                 )

        #預測按鈕
        self.btnclass=QPushButton()
        self.btnclass.setText('點擊預測分類')
        self.btnclass.clicked.connect(self.fenlei)
        self.labelclass=QLabel()
        self.labelclass.setText('預測類別')
        self.labelclass.setStyleSheet("font:16pt '楷體';border-width:2px;border-style: inset;border-color:gray")




        layout1=QVBoxLayout()
        layout1.addWidget(self.btn)
        layout1.addWidget(self.label)
        layout1.addWidget(self.labelimage)

        layout2 = QVBoxLayout()
        layout2.addWidget(self.btnclass)
        layout2.addWidget(self.labelclass)

        layout=QVBoxLayout()
        layout.addLayout(layout1)
        layout.addLayout(layout2)

        self.setLayout(layout)

    def openimage(self):
        imgName, imgType = QFileDialog.getOpenFileName(self, "打開圖片", "", "*.jpg;;*.png;;All Files(*)")
        #jpg = QtGui.QPixmap(imgName).scaled(self.labelimage.width(), self.label.height())#適應labelimage尺寸,前提是label設置了尺寸
        jpg = QtGui.QPixmap(imgName)
        self.labelimage.setPixmap(jpg)
        self.label.setText(str(imgName))
    def fenlei(self):
        biaoqian = {'1': '貓', '0': '狗'}
        path=self.label.text()
        newName = re.sub('(D:/機器學習/學習草稿/)','', path)
        #print(newName)
        img = cv2.imread(str(newName))


        img = cv2.resize(img, (100, 100))  # 使尺寸大小同樣
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        img = np.array(img) / 255
        img = img.astype(np.float64)
        img = img.reshape(-1, 100, 100, 1)
        model = load_model('貓狗分類.h5')
        predict_y = model.predict(img)
        pred_y = int(np.round(predict_y))
        #print(pred_y)
        self.labelclass.setText(biaoqian[str(pred_y)])

        ########圖像定位

        src = cv2.imread(str(newName))
        src = cv2.resize(src, None, fx=0.5, fy=0.5)
        image = src.copy()
        # 去噪
        blurred = cv2.GaussianBlur(image, (5, 5), 0)  # 去噪
        # 灰度轉換
        gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
        # 二值化
        ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        # 輪廓發現
        contours, hireachy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        # 取出最大輪廓
        c = sorted(contours, key=cv2.contourArea, reverse=True)[0]
        # 找到最大輪廓的最小外接矩形
        rect = cv2.minAreaRect(c)
        # 取出最小外接矩形的四個頂點
        box = np.int0(cv2.boxPoints(rect))
        # 繪製矩形框
        Xs = [i[0] for i in box]
        Ys = [i[1] for i in box]
        x1 = min(Xs)
        x2 = max(Xs)
        y1 = min(Ys)
        y2 = max(Ys)
        hight = y2 - y1
        width = x2 - x1
        cropImg = image[y1:y1 + hight, x1:x1 + width]
        cv2.rectangle(image, (x1, y1), (x1 + width, y1 + hight), (0, 0, 255), 2)  # 在原圖上,給輪廓繪製矩形


        #顯示在lableimage上


        res = image
        res = cv2.resize(res, (400, 300), interpolation=cv2.INTER_CUBIC)  # 用cv2.resize設置圖片大小
        img2 = cv2.cvtColor(res, cv2.COLOR_BGR2RGB)  # opencv讀取的bgr格式圖片轉換成rgb格式
        _image = QtGui.QImage(img2[:], img2.shape[1], img2.shape[0], img2.shape[1] * 3,
                              QtGui.QImage.Format_RGB888)  # pyqt5轉換成本身能放的圖片格式
        jpg_out = QtGui.QPixmap(_image)  # 轉換成QPixmap
        self.labelimage.setPixmap(jpg_out)  # 設置圖片顯示

        cv2.waitKey()
        cv2.destroyAllWindows()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    my = picture()
    my.show()
    sys.exit(app.exec_())

說明:

model = load_model(‘貓狗分類.h5’)
導入訓練好的分類模型

在PYQT中顯示opencv圖 核心代碼

def setImage(self):
        img = cv2.imread('test.jpg') #opencv讀取圖片
        img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) #opencv讀取的bgr格式圖片轉換成rgb格式
        _image = QtGui.QImage(img2[:], img2.shape[1], img2.shape[0], img2.shape[1] * 3, QtGui.QImage.Format_RGB888) #pyqt5轉換成本身能放的圖片格式
        jpg_out = QtGui.QPixmap(_image).scaled(self.imgLabel.width(), self.imgLabel.height()) #設置圖片大小
        self.imgLabel.setPixmap(jpg_out) #設置圖片顯示

結果演示

本文給出的方法不是純粹的目標檢測算法。定位有的圖有所缺陷。

只是圖像分類+對象測量 來實現單一目標檢測功能

等我有時間研究下目標檢測算法後,再來寫博文。

電氣專業的計算機萌新,寫博文不容易,若是你以爲本文對你有用,請點個贊支持下,謝謝。

在這裏插入圖片描述

相關文章
相關標籤/搜索