機器學習 - 圖像識別

圖像識別

OpenCV基礎

OpenCV是一個開源的計算機視覺庫。提供了很多圖像處理常用的工具。

案例:

import numpy as np
import cv2 as cv
# 讀取圖片並顯示
original = cv.imread('../data/forest.jpg')
cv.imshow('Original', original)
# 顯示圖片某個顏色通道的圖像
blue = np.zeros_like(original)
blue[:, :, 0] = original[:, :, 0]  # 0 - 藍色通道
cv.imshow('Blue', blue)
green = np.zeros_like(original)
green[:, :, 1] = original[:, :, 1]  # 1 - 綠色通道
cv.imshow('Green', green)
red = np.zeros_like(original)
red[:, :, 2] = original[:, :, 2]  # 2 - 紅色通道
cv.imshow('Red', red)
# 圖像裁剪
h, w = original.shape[:2]
l, t = int(w / 4), int(h / 4)
r, b = int(w * 3 / 4), int(h * 3 / 4)
cropped = original[t:b, l:r]
cv.imshow('Cropped', cropped)
#圖像縮放 interpolation=線型插值
scaled1 = cv.resize(original, (int(w / 4), int(h / 4)),
    interpolation=cv.INTER_LINEAR)
cv.imshow('Scaled1', scaled1)
scaled2 = cv.resize(
    scaled1, None, fx=4, fy=4,
    interpolation=cv.INTER_LINEAR)
cv.imshow('Scaled2', scaled2)
cv.waitKey()
# 圖像文件保存
cv.imwrite('../../data/blue.jpg', blue)
cv.imwrite('../../data/green.jpg', green)
cv.imwrite('../../data/red.jpg', red)
cv.imwrite('../../data/cropped.jpg', cropped)
cv.imwrite('../../data/scaled1.jpg', scaled1)
cv.imwrite('../../data/scaled2.jpg', scaled2)

邊緣檢測

物體的邊緣檢測是物體識別常用的手段。邊緣檢測常用亮度梯度方法。通過識別亮度梯度變化最大的像素點從而檢測出物體的邊緣。

常用邊緣檢測算法相關API:

# 索貝爾邊緣識別
# cv.CV_64F:卷積運算使用數據類型爲64位浮點型(保證微分的精度)
# 1:水平方向索貝爾偏微分
# 0:垂直方向索貝爾偏微分
# ksize:卷積核爲5*5的方陣
cv.Sobel(original, cv.CV_64F, 1, 0, ksize=5)
# 拉普拉斯邊緣識別
cv.Laplacian(original, cv.CV_64F)
# Canny邊緣識別
# 50:水平方向閾值  240:垂直方向閾值
cv.Canny(original, 50, 240)

案例:

import cv2 as cv

original = cv.imread( '../data/chair.jpg', cv.IMREAD_GRAYSCALE)
cv.imshow('Original', original)
hsobel = cv.Sobel(original, cv.CV_64F, 1, 0, ksize=5)
cv.imshow('H-Sobel', hsobel)
vsobel = cv.Sobel(original, cv.CV_64F, 0, 1, ksize=5)
cv.imshow('V-Sobel', vsobel)
sobel = cv.Sobel(original, cv.CV_64F, 1, 1, ksize=5)
cv.imshow('Sobel', sobel)
laplacian = cv.Laplacian(original, cv.CV_64F)
cv.imshow('Laplacian', laplacian)
canny = cv.Canny(original, 50, 240)
cv.imshow('Canny', canny)
cv.waitKey()

亮度提升

OpenCV提供了直方圖均衡化的方式實現亮度提升,更有利於邊緣識別與物體識別模型的訓練。

OpenCV直方圖均衡化相關API:

# 彩色圖轉爲灰度圖
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
# 直方圖均衡化
equalized_gray = cv.equalizeHist(gray)

案例:

import cv2 as cv

original = cv.imread('../../data/sunrise.jpg')
cv.imshow('Original', original)
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
cv.imshow('Gray', gray)
equalized_gray = cv.equalizeHist(gray)
cv.imshow('Equalized Gray', equalized_gray)
# YUV:亮度,色度,飽和度
yuv = cv.cvtColor(original, cv.COLOR_BGR2YUV)
yuv[..., 0] = cv.equalizeHist(yuv[..., 0])
equalized_color = cv.cvtColor(yuv, cv.COLOR_YUV2BGR)
cv.imshow('Equalized Color', equalized_color)
cv.waitKey()

角點檢測

平直棱線的交匯點(顏色梯度方向改變的像素點的位置)

OpenCV提供的角點檢測相關API:

gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
# Harris角點檢測器
# 邊緣水平方向、垂直方向顏色值改變超過閾值7、5時即爲邊緣
# 邊緣線方向改變超過閾值0.04弧度即爲一個角點。
corners = cv.cornerHarris(gray, 7, 5, 0.04)

案例:

import cv2 as cv

original = cv.imread('../data/box.png')
cv.imshow('Original', original)
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
cv.imshow('Gray', gray)
corners = cv.cornerHarris(gray, 7, 5, 0.04)
mixture = original.copy()
mixture[corners > corners.max() * 0.01] = [0, 0, 255]
cv.imshow('Corner', mixture)
cv.waitKey()

特徵點檢測

常用特徵點檢測有:STAR特徵點檢測 / SIFT特徵點檢測

特徵點檢測結合了邊緣檢測與角點檢測從而識別出圖形的特徵點。

STAR特徵點檢測相關API如下:

import cv2 as cv
# 創建STAR特徵點檢測器
star = cv.xfeatures2d.StarDetector_create()
# 檢測出gray圖像所有的特徵點
keypoints = star.detect(gray)
# drawKeypoints方法可以把所有的特徵點繪製在mixture圖像中
cv.drawKeypoints(original, keypoints, mixture,
    			 flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imshow('Mixture', mixture)

案例:

import cv2 as cv
original = cv.imread('../data/table.jpg')
cv.imshow('Original', original)
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
cv.imshow('Gray', gray)
star = cv.xfeatures2d.StarDetector_create()
keypoints = star.detect(gray)
mixture = original.copy()
cv.drawKeypoints(
    original, keypoints, mixture,
    flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imshow('Mixture', mixture)
cv.waitKey()

SIFT特徵點檢測相關API:

import cv2 as cv

# 創建SIFT特徵點檢測器
sift = cv.xfeatures2d.SIFT_create()
keypoints = sift.detect(gray)

案例:

import cv2 as cv

original = cv.imread('../data/table.jpg')
cv.imshow('Original', original)
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
cv.imshow('Gray', gray)
sift = cv.xfeatures2d.SIFT_create()
keypoints = sift.detect(gray)
mixture = original.copy()
cv.drawKeypoints(original, keypoints, mixture,
    flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv.imshow('Mixture', mixture)
cv.waitKey()

特徵值矩陣

圖像特徵值矩陣(描述)記錄了圖像的特徵點以及每個特徵點的梯度信息,相似圖像的特徵值矩陣也相似。這樣只要有足夠多的樣本,就可以基於隱馬爾科夫模型進行圖像內容的識別。

特徵值矩陣相關API:

sift = cv.xfeatures2d.SIFT_create()
keypoints = sift.detect(gray)
_, desc = sift.compute(gray, keypoints)

案例:

import cv2 as cv

import matplotlib.pyplot as mp
original = cv.imread('../data/table.jpg')
cv.imshow('Original', original)
gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)
cv.imshow('Gray', gray)
sift = cv.xfeatures2d.SIFT_create()
keypoints = sift.detect(gray)
_, desc = sift.compute(gray, keypoints)
print(desc.shape)
mp.matshow(desc, cmap='jet', fignum='Description')
mp.title('Description', fontsize=20)
mp.xlabel('Feature', fontsize=14)
mp.ylabel('Sample', fontsize=14)
mp.tick_params(which='both', top=False, labeltop=False, labelbottom=True, labelsize=10)
mp.show()

物體識別

import os
import numpy as np
import cv2 as cv
import hmmlearn.hmm as hl

def search_files(directory):
    directory = os.path.normpath(directory)

    objects = {}
    for curdir, subdirs, files in os.walk(directory):
        for file in files:
            if(file.endswith('.jpg')):
                label = curdir.split(os.path.sep)[-1]
                if label not in objects:
                    objects[label] = []
                path = os.path.join(curdir, file)
                objects[label].append(path)
    return objects
	
#加載訓練集樣本數據,訓練模型,模型存儲
train_objects = search_files('../data/objects/training')
train_x, train_y = [], []
for label, filenames in train_objects.items():
    descs = np.array([])
    for filename in filenames:
        image = cv.imread(filename)
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        #範圍縮放,使特徵描述矩陣樣本數量一致
        h, w = gray.shape[:2]
        f = 200 / min(h, w)
        gray = cv.resize(gray, None, fx=f, fy=f)
        sift = cv.xfeatures2d.SIFT_create()
        keypoints = sift.detect(gray)
        _, desc = sift.compute(gray, keypoints)
        if len(descs) == 0:
            descs = desc
        else:
            descs = np.append(descs, desc, axis=0)
    train_x.append(descs)
    train_y.append(label)
models = {}
for descs, label in zip(train_x, train_y):
    model = hl.GaussianHMM(n_components=4, covariance_type='diag', n_iter=100)
    models[label] = model.fit(descs)


#測試模型
test_objects = search_files('../data/objects/testing')
test_x, test_y = [], []
for label, filenames in test_objects.items():
    descs = np.array([])
    for filename in filenames:
        image = cv.imread(filename)
        gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
        sift = cv.xfeatures2d.SIFT_create()
        keypoints = sift.detect(gray)
        _, desc = sift.compute(gray, keypoints)
        if len(descs) == 0:
            descs = desc
        else:
            descs = np.append(descs, desc, axis=0)
    test_x.append(descs)
    test_y.append(label)

# 遍歷所有測試樣本  使用model匹配測試樣本查看每個模型的匹配分數
for descs, test_label in zip(test_x, test_y):
    for pred_label, model in models.items():
        score = model.score(descs)
        print(test_label, '->', pred_label, score)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章