I'm a newbie here in Image Recognition. Currently, I'm making traffic sign detection from a video using OpenCV library in python. It work well if I use template matching function that provided by openCV. But when I tried to use ORB, it works well on single image of the object i want to recognize and completely useless if I feed a video to the program. So, I take an approach which split the video feed as 4 different section. Here is the code I created:
import numpy as np
import cv2
import os
orb = cv2.ORB_create(10000)
# orb = cv2.ORB_create(10000, nlevels=8, edgeThreshold=5)
PATH_TEMPLATE = "img/template"
images = []
classNames = []
classFound = [0,0]
path_list = os.listdir(PATH_TEMPLATE)
for className in path_list:
currentImage = cv2.imread(f'{PATH_TEMPLATE}/{className}',0)
# currentImage = cv2.resize(currentImage, (0,0), fx=0.7, fy=0.7)
images.append(currentImage)
classNames.append(className.split(".")[0])
print(classNames)
# Create Descriptor for each image class
def createDesc(images):
descList = []
for img in images:
keypoint, descriptor = orb.detectAndCompute(img,None)
descList.append(descriptor)
return descList
descList = createDesc(images)
print(len(descList))
# print(descList)
# Create matcher
def checkMatch(img, descList):
img_keypoint, img_descriptor = orb.detectAndCompute(img,None)
# print(img_descriptor)
bf = cv2.BFMatcher()
matchListLen = []
matchList = []
# Loop trough defined Class Descriptor
for desc in descList:
if (img_descriptor is not None):
matches = bf.knnMatch(desc, img_descriptor, k=2)
goodMatches = []
# Loop Through matches
for m,n in matches:
# Check if the matches near to each other
if m.distance < 0.75 * n.distance:
goodMatches.append([m])
# Loop Through matches
# for x in range(0, len(matches) - 1):
# # Check if the matches near to each other
# if matches[x][0].distance < 0.5 * matches[x + 1][0].distance:
# goodMatches.append([matches[x]])
matchListLen.append(len(goodMatches))
matchList.append(goodMatches)
return matchList, matchListLen
#Find detected class
def getClass(matches, threshold = 15):
# print(matches)
finalClass = -1
if (len(matches) != 0):
if max(matches) > threshold:
finalClass = matches.index(max(matches))
return finalClass
def singleObjDetect(filename):
#Test image
imgTest = cv2.imread(f"img/{filename}")
imgTestG = imgTest.copy()
# imgTestG = cv2.cvtColor(imgTestG, cv2.COLOR_BGR2GRAY)
matchRaw, matchLen = checkMatch(imgTestG, descList)
classID = getClass(matchLen)
if (classID != -1):
print(f'Detected: {classNames[classID]}')
else:
print("Undetected")
def sceneObjDetect(filename):
imgTest = cv2.imread(f"img/{filename}")
imgTestG = imgTest.copy()
M = imgTestG.shape[0] // 3
N = imgTestG.shape[1] // 3
imgTestG = imgTestG[0:M*3, 0:N*3]
imgTiles = [imgTestG[x:x+M,y:y+N] for x in range(0, imgTestG.shape[0], M) for y in range(0, imgTestG.shape[1], N) ]
for x in range(0, len(imgTiles)):
print(f'Tile: {x}')
matchRaw, matchLen = checkMatch(imgTiles[x], descList)
classID = getClass(matchLen)
if (classID != -1):
print(f'Detected: {classNames[classID]}')
else:
print("Undetected")
cv2.imshow(f'Tile {x}', imgTiles[x])
cv2.waitKey(0)
def sceneRealObjDetect(filename, threshold = 15):
vid = cv2.VideoCapture(f"vid/{filename}")
while True:
ret, frame = vid.read()
if not ret:
break
imgTestG = frame.copy()
# imgTestG = cv2.cvtColor(imgTestG, cv2.COLOR_BGR2GRAY)
M = imgTestG.shape[0] // 2
N = imgTestG.shape[1] // 2
imgTestG = imgTestG[0:M*2, 0:N*2]
# print(f"H:{imgTestG.shape[0]} W:{imgTestG.shape[1]}")
imgTiles = [imgTestG[x:x+M,y:y+N] for x in range(0, imgTestG.shape[0], M) for y in range(0, imgTestG.shape[1], N) ]
for x in range(0, len(imgTiles)):
# print(f'Tile: {x}')
# print(f'Tile Size {imgTiles[x].shape[1]} x {imgTiles[x].shape[0]}')
matchRaw, matchLen = checkMatch(imgTiles[x], descList)
classID = getClass(matchLen,threshold)
if (classID != -1):
# print(f'Detected: {classNames[classID]}')
classFound[classID] += 1
cv2.putText(imgTiles[x], f'Detected: {classNames[classID]} deb: {matchLen}',(imgTiles[x].shape[1] // 2, imgTiles[x].shape[0] // 2),cv2.FONT_HERSHEY_PLAIN, 1, (0,255,0), 1)
else:
# print("Undetected")
cv2.putText(imgTiles[x], f"Undetected deb: {matchLen}",(imgTiles[x].shape[1] // 2, imgTiles[x].shape[0] // 2),cv2.FONT_HERSHEY_PLAIN, 1, (0,0,255), 1)
cv2.imshow(f'Tile: {x}', imgTiles[x])
# cv2.imshow("Video", vid)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
vid.release()
# testing
sceneRealObjDetect("test-drive-720.mp4", 18)
print(classFound)
# singleObjDetect("green-life.png")
I wonder how to detect multiple traffic sign recognition without spliting the video into 4 section. I hvae tried some different approach but it resulting error. Since, I'm a newbie i want to know how to achieve the multiple traffic sign detection using ORB.