1. 程式人生 > 其它 >OpenCV的一些影象處理演算法

OpenCV的一些影象處理演算法

技術標籤:筆記opencv影象識別

OpenCV的一些影象處理演算法

訓練完電賽滾球題,剛比完資料賽,總結一下用到的一些影象處理演算法
(寫到後面覺得好長,資料賽的寫在另一篇部落格https://blog.csdn.net/qq_45615475/article/details/112860120
閾值提取
在這裡插入圖片描述

#定義各類顏色閾值範圍
import numpy as np
#黑色
lower_black=np.array([0,0,0])
upper_black=np.array([180,255,46])
#灰色
lower_gray=np.array([0,0,46])
upper_gray=np.array([180,43,220])
#白色
lower_white=np.array([0,0,221])
upper_white=np.array([180,30,255])
#紅色
lower_red1=np.array([0,43,46])
upper_red1=np.array([10,255,255])
lower_red2=np.array([156,43,46])
upper_red2=np.array([180,255,255])
#橙色
lower_orange=np.array([11,43,46])
upper_orange=np.array([25,255,255])
#黃色
lower_yellow=np.array([26,43,46])
upper_yellow=np.array([34,255,255])
#青色
lower_qin=np.array([78,43,46])
upper_qin=np.array([99,255,255])
#藍色
lower_blue=np.array([100,43,46])
upper_blue=np.array([124,255,255])
#紫色
lower_purple=np.array([125,43,46])
upper_purple=np.array([155,255,255])
img_path='Test/Test1.png'
img=cv2.imread(img_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)#轉換為HSV空間
mask = cv2.inRange(hsv, lower_red, upper_red)#根據閾值提取紅色,想提取其他顏色就改為對應閾值即可

二值化

gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#影象灰度化
ret,thresh = cv2.threshold(gray_img,80,255,cv2.THRESH_BINARY)#需要設定提取閾值

霍夫圓檢測
小球識別一開始用的方案,但太耗時,最後還是直接色塊檢測

lower = np.array([0, 0, 0])  # 設定顏色的閾值下限
upper = np.array([120, 120, 120])  # 設定顏色的閾值上限
#  消除噪聲
mask = cv2.inRange(hsv, lower, upper)  # 設定掩膜取值範圍
#bila = cv2.bilateralFilter(mask, 10, 200, 200)  # 雙邊濾波消除噪聲
#opening = cv2.morphologyEx(bila, cv2.MORPH_OPEN, kernel)  # 形態學開運算
#closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel)  # 形態學開運算
#edges = cv2.Canny(closing, 50, 100) # 邊緣識別 edges = cv2.Canny(mask, 50, 100) # 邊緣識別 circles = cv2.HoughCircles( edges, cv2.cv.CV_HOUGH_GRADIENT, 1, 100, param1=100, param2=10, minRadius=10, maxRadius=500) if circles is not None: # 如果識別出圓 for circle in circles[0]: # 獲取圓的座標與半徑 x = int(circle[0]) y = int(circle[1]) r = int(circle[2]) cv2.circle(frame, (x, y), r, (0, 0, 255), 3) # 標記圓 cv2.circle(frame, (x, y), 3, (255, 255, 0), -1) # 標記圓心 text = 'x: '+str(x)+' y: '+str(y) cv2.putText(frame, text, (10, 30), font, 1, (0, 255, 0), 2) # 顯示圓心位置 else: # 如果識別不出,顯示圓心不存在 cv2.putText(frame, 'x: None y: None', (10, 30), font, 1, (0, 255, 0), 2)
#輸入影象,輸出畫圓的影象
def Get_Circles(frame):

    gray = cv2.cvtColor(frame, cv2.COLOR_BGRA2GRAY)
    img = cv2.medianBlur(gray, 7)
    circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=70, maxRadius=200)#霍夫圓檢測
    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0, :]:  # 在圖片上畫圓和圓心
            cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
            cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
    return frame
#找紅球
def Get_Red_Circles(frame):
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, lower_red, upper_red)
    res = cv2.bitwise_and(frame, frame, mask=mask)
    gray = cv2.cvtColor(res, cv2.COLOR_BGRA2GRAY)
    img = cv2.medianBlur(gray, 7)
    circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=70, maxRadius=200)#霍夫圓檢測
    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0, :]:  # 在圖片上畫圓和圓心
            cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
            cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
    return frame

色塊檢測

cnts = cv2.findContours(thresh1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]  #輪廓檢測
#如果存在輪廓  
if len(cnts) > 0:  
    #找到面積最大的輪廓  
    c = max(cnts, key = cv2.contourArea)  
    #確定面積最大的輪廓的外接圓  
    ((center_x, center_y), radius) = cv2.minEnclosingCircle(c)  
    #計算輪廓的矩  
    # M = cv2.moments(c)  
    #計算質心  
    cv2.circle(frame, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)  
    cv2.circle(frame, None, 5, (0, 0, 255), -1)
    print('紅色色塊的中心座標',(int(center_x),int(center_y)))
#通過二值化和色塊檢測得到小球座標
lower_red=np.array([156,43,46])
upper_red=np.array([180,255,255])
def Binary_Get_Ball(frame,show,area,thr):
    cropped = frame[area[0]:area[1], area[2]:area[3]]  #(上,下)(左,右)
    gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#影象灰度化
    ret,thresh=cv2.threshold(gray_img,thr[0],thr[1],cv2.THRESH_BINARY)
    thresh=255-thresh
    cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]  #輪廓檢測
    #如果存在輪廓  
    if len(cnts) > 0:  
        #找到面積最大的輪廓  
        c = max(cnts, key = cv2.contourArea)  
        #確定面積最大的輪廓的外接圓  
        ((center_x, center_y), radius) = cv2.minEnclosingCircle(c)  
        if (show==True): 
            cv2.circle(cropped, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)  
            cv2.circle(cropped, None, 5, (0, 0, 255), -1)
        print('紅色色塊的中心座標',(int(center_x),int(center_y)))
    else:
        center_x=0
        center_y=0
        radius=0
    return center_x,center_y,radius,cropped

電賽滾球題最終方案
可見我另一篇文章https://blog.csdn.net/qq_45615475/article/details/112859548

形態學開運算/閉運算
好像有以下程式碼可以執行

opening = cv2.morphologyEx(bila, cv2.MORPH_OPEN, kernel) # 形態學開運算 
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel) # 形態學閉運算

但我一般都是直接膨脹腐蝕(閉運算)或者腐蝕膨脹(開運算)看每一步的效果效果

#iterations為整數,可調,越大效果越強
no_img1 = cv2.dilate(no_img1, None, iterations=1)#膨脹
no_img1 = cv2.erode(no_img1, None, iterations=1)#腐蝕

濾波
雙邊濾波消除噪聲

bila = cv2.bilateralFilter(mask, 10, 200, 200) # 雙邊濾波消除噪聲 # 

高斯濾波

中值模糊

img = cv.medianBlur(gay_img, 7)  # 進行中值模糊,去噪點

edges = cv2.Canny(closing, 50, 100) # 邊緣識別

影象變換

gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)#影象灰度化
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)#轉換為HSV空間

透視變換

def PersTrans(frame,Center,frame_points): #透視變換,輸入為影象
    rows,cols,channel = frame.shape
    src_points = np.float32([Center[0],Center[1],Center[2],Center[3]])
    dst_points = np.float32([[0,0],[cols-1,0],[0,rows-1],[cols-1,rows-1]])
    projective_martix = cv2.getPerspectiveTransform(src_points,dst_points)
    projective_image = cv2.warpPerspective(frame,projective_martix,(cols,rows))
    return projective_image,projective_martix

影象擷取部分

cropped = img[30:440, 140:540]  #(上,下)(左,右)