1.研究背景
近年來(lái),隨著計(jì)算機(jī)視覺(jué)技術(shù)的快速發(fā)展,人們對(duì)于圖像處理和模式識(shí)別的需求也越來(lái)越大。其中,魔方識(shí)別系統(tǒng)是一個(gè)備受關(guān)注的研究領(lǐng)域。魔方作為一種具有復(fù)雜結(jié)構(gòu)和多變性的立體拼圖,其解決方案一直是計(jì)算機(jī)視覺(jué)領(lǐng)域的一項(xiàng)挑戰(zhàn)。而Python和OpenCV作為目前最流行的圖像處理工具,被廣泛應(yīng)用于魔方識(shí)別系統(tǒng)的開(kāi)發(fā)中。
傳統(tǒng)的魔方識(shí)別方法主要依賴于人工操作和視覺(jué)判斷,這種方法存在識(shí)別速度慢、準(zhǔn)確率低等問(wèn)題。而基于計(jì)算機(jī)視覺(jué)的魔方識(shí)別系統(tǒng)可以通過(guò)圖像處理和模式識(shí)別技術(shù),實(shí)現(xiàn)對(duì)魔方的自動(dòng)識(shí)別和還原。這不僅可以提高魔方的解決效率,還可以為魔方愛(ài)好者提供一個(gè)更加便捷和準(zhǔn)確的解決方案。
Python作為一種簡(jiǎn)潔、易學(xué)、功能強(qiáng)大的編程語(yǔ)言,具有豐富的圖像處理庫(kù)和機(jī)器學(xué)習(xí)工具,適合用于魔方識(shí)別系統(tǒng)的開(kāi)發(fā)。而OpenCV作為一個(gè)開(kāi)源的計(jì)算機(jī)視覺(jué)庫(kù),提供了豐富的圖像處理和模式識(shí)別算法,可以方便地實(shí)現(xiàn)對(duì)魔方圖像的處理和分析。

2.研究?jī)?nèi)容和意義
本研究的目的是基于Python和OpenCV開(kāi)發(fā)一個(gè)魔方識(shí)別系統(tǒng),并提供相應(yīng)的源碼和部署教程。通過(guò)該系統(tǒng),用戶可以將魔方的圖像輸入,系統(tǒng)可以自動(dòng)識(shí)別魔方的狀態(tài),并給出相應(yīng)的還原方案。具體來(lái)說(shuō),本研究的主要內(nèi)容包括以下幾個(gè)方面:
圖像預(yù)處理:通過(guò)使用OpenCV提供的圖像處理算法,對(duì)輸入的魔方圖像進(jìn)行預(yù)處理,包括圖像去噪、邊緣檢測(cè)、圖像分割等操作,以提高后續(xù)的識(shí)別準(zhǔn)確率。
特征提取與模式識(shí)別:通過(guò)使用OpenCV提供的特征提取算法,對(duì)預(yù)處理后的圖像進(jìn)行特征提取,以獲取魔方的狀態(tài)信息。然后,通過(guò)機(jī)器學(xué)習(xí)算法,對(duì)提取到的特征進(jìn)行模式識(shí)別,以確定魔方的狀態(tài)。
還原方案生成:根據(jù)識(shí)別到的魔方狀態(tài),使用經(jīng)典的還原算法,生成相應(yīng)的還原方案。通過(guò)該方案,用戶可以輕松地還原魔方,提高解決效率。
本研究的意義主要體現(xiàn)在以下幾個(gè)方面:
提高魔方解決效率:傳統(tǒng)的魔方解決方法主要依賴于人工操作和視覺(jué)判斷,效率較低。而基于計(jì)算機(jī)視覺(jué)的魔方識(shí)別系統(tǒng)可以實(shí)現(xiàn)對(duì)魔方的自動(dòng)識(shí)別和還原,大大提高了解決效率。
推動(dòng)計(jì)算機(jī)視覺(jué)技術(shù)的發(fā)展:本研究基于Python和OpenCV開(kāi)發(fā)魔方識(shí)別系統(tǒng),將為計(jì)算機(jī)視覺(jué)技術(shù)的研究和應(yīng)用提供一個(gè)實(shí)際的案例。同時(shí),通過(guò)提供源碼和部署教程,可以幫助更多的開(kāi)發(fā)者學(xué)習(xí)和應(yīng)用計(jì)算機(jī)視覺(jué)技術(shù)。
拓展魔方應(yīng)用領(lǐng)域:魔方作為一種立體拼圖,具有廣泛的應(yīng)用領(lǐng)域,如機(jī)器人導(dǎo)航、虛擬現(xiàn)實(shí)等。通過(guò)開(kāi)發(fā)魔方識(shí)別系統(tǒng),可以為這些應(yīng)用領(lǐng)域提供一個(gè)更加便捷和準(zhǔn)確的解決方案。
總之,基于Python和OpenCV開(kāi)發(fā)的魔方識(shí)別系統(tǒng)具有重要的研究意義和應(yīng)用價(jià)值。通過(guò)該系統(tǒng),可以提高魔方的解決效率,推動(dòng)計(jì)算機(jī)視覺(jué)技術(shù)的發(fā)展,并拓展魔方的應(yīng)用領(lǐng)域。同時(shí),通過(guò)提供源碼和部署教程,可以幫助更多的開(kāi)發(fā)者學(xué)習(xí)和應(yīng)用計(jì)算機(jī)視覺(jué)技術(shù)。
3.圖片演示



4.視頻演示
Python+OpenCV魔方識(shí)別系統(tǒng)(源碼和部署教程)_嗶哩嗶哩_bilibili
5.核心代碼講解
5.1 colordetection.py
class ColorDetection:
def __init__(self):
self.prominent_color_palette = {
'red' : (0, 0, 255),
'orange': (0, 165, 255),
'blue' : (255, 0, 0),
'green' : (0, 255, 0),
'white' : (255, 255, 255),
'yellow': (0, 255, 255)
}
# Load colors from config and convert the list -> tuple.
self.cube_color_palette = config.get_setting(
CUBE_PALETTE,
self.prominent_color_palette
)
for side, bgr in self.cube_color_palette.items():
self.cube_color_palette[side] = tuple(bgr)
def get_prominent_color(self, bgr):
"""Get the prominent color equivalent of the given bgr color."""
for color_name, color_bgr in self.cube_color_palette.items():
if tuple([int(c) for c in bgr]) == color_bgr:
return self.prominent_color_palette[color_name]
return COLOR_PLACEHOLDER
def get_dominant_color(self, roi):
"""
Get dominant color from a certain region of interest.
:param roi: The image list.
:returns: tuple
"""
pixels = np.float32(roi.reshape(-1, 3))
n_colors = 1
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 200, .1)
flags = cv2.KMEANS_RANDOM_CENTERS
_, labels, palette = cv2.kmeans(pixels, n_colors, None, criteria, 10, flags)
_, counts = np.unique(labels, return_counts=True)
dominant = palette[np.argmax(counts)]
return tuple(dominant)
def get_closest_color(self, bgr):
"""
Get the closest color of a BGR color using CIEDE2000 distance.
:param bgr tuple: The BGR color to use.
:returns: dict
"""
lab = bgr2lab(bgr)
distances = []
for color_name, color_bgr in self.cube_color_palette.items():
distances.append({
'color_name': color_name,
'color_bgr': color_bgr,
'distance': ciede2000(lab, bgr2lab(color_bgr))
})
closest = min(distances, key=lambda item: item['distance'])
return closest
def convert_bgr_to_notation(self, bgr):
"""
Convert BGR tuple to rubik's cube notation.
The BGR color must be normalized first by the get_closest_color method.
:param bgr tuple: The BGR values to convert.
:returns: str
"""
notations = {
'green' : 'F',
'white' : 'U',
'blue' : 'B',
'red' : 'R',
'orange': 'L',
'yellow': 'D'
}
color_name = self.get_closest_color(bgr)['color_name']
return notations[color_name]
def set_cube_color_pallete(self, palette):
"""
Set a new cube color palette. The palette is being used when the user is
scanning his cube in solve mode by matching the scanned colors against
this palette.
"""
for side, bgr in palette.items():
self.cube_color_palette[side] = tuple([int(c) for c in bgr])
color_detector = ColorDetection()
這段代碼定義了一個(gè)名為ColorDetection的類,用于顏色檢測(cè)。其中包含了以下方法:
-
__init__(self): 初始化方法,設(shè)置了默認(rèn)的顏色列表。 -
get_prominent_color(self, bgr): 根據(jù)給定的BGR顏色獲取對(duì)應(yīng)的主要顏色。 -
get_dominant_color(self, roi): 從給定的感興趣區(qū)域獲取主要顏色。 -
get_closest_color(self, bgr): 根據(jù)給定的BGR顏色,使用CIEDE2000距離獲取最接近的顏色。 -
convert_bgr_to_notation(self, bgr): 將BGR顏色轉(zhuǎn)換為魔方符號(hào)表示。 -
set_cube_color_pallete(self, palette): 設(shè)置新的魔方顏色列表。
最后,創(chuàng)建了一個(gè)ColorDetection的實(shí)例color_detector。
該程序文件名為colordetection.py,是一個(gè)顏色檢測(cè)的類。該類包含以下方法:
__init__(self):初始化方法,定義了顏色的調(diào)色板,包括突出顏色調(diào)色板和魔方顏色調(diào)色板。get_prominent_color(self, bgr):根據(jù)給定的BGR顏色獲取對(duì)應(yīng)的突出顏色。get_dominant_color(self, roi):從給定的感興趣區(qū)域獲取主要顏色。get_closest_color(self, bgr):使用CIEDE2000距離獲取給定BGR顏色的最接近顏色。convert_bgr_to_notation(self, bgr):將BGR顏色轉(zhuǎn)換為魔方符號(hào)表示。set_cube_color_pallete(self, palette):設(shè)置新的魔方顏色調(diào)色板。color_detector = ColorDetection():創(chuàng)建一個(gè)ColorDetection對(duì)象。
該程序還導(dǎo)入了以下模塊和文件:
numpy:用于處理數(shù)組和矩陣的庫(kù)。cv2:OpenCV庫(kù),用于圖像處理和計(jì)算機(jī)視覺(jué)。helpers:自定義的輔助函數(shù)模塊。config:自定義的配置模塊。constants:自定義的常量模塊。
需要注意的是,該程序文件中的代碼是一個(gè)類的定義,沒(méi)有實(shí)際執(zhí)行的部分。要使用該類,需要在其他地方創(chuàng)建一個(gè)ColorDetection對(duì)象,并調(diào)用其方法。
5.2 config.py
class Config:
def __init__(self):
self.config_dir = os.path.expanduser('~/.config/qbr')
self.settings_file = os.path.join(self.config_dir, 'settings.json')
try:
self.settings = json.loads(open(self.settings_file, 'r').read())
except Exception:
self.settings = {}
if not os.path.exists(self.config_dir):
os.mkdir(self.config_dir)
def get_setting(self, key, default_value=None):
"""Get a specific key from the settings."""
if key in self.settings:
return self.settings[key]
if default_value is not None:
return default_value
return None
def set_setting(self, key, value):
"""Set a specific setting and save it."""
self.settings[key] = value
with open(self.settings_file, 'w') as f:
json.dump(self.settings, f)
f.close()
這個(gè)程序文件名為config.py,它是一個(gè)用于處理配置文件的類。該類包含以下方法和屬性:
-
__init__(self):初始化方法,設(shè)置配置文件的目錄和文件路徑,并嘗試加載配置文件。如果配置文件不存在,則創(chuàng)建目錄。 -
config_dir:配置文件的目錄路徑。 -
settings_file:配置文件的完整路徑。 -
settings:存儲(chǔ)配置項(xiàng)的字典。 -
get_setting(self, key, default_value=None):從配置項(xiàng)中獲取指定的鍵值。如果鍵存在,則返回對(duì)應(yīng)的值;如果鍵不存在且提供了默認(rèn)值,則返回默認(rèn)值;否則返回None。 -
set_setting(self, key, value):設(shè)置指定的配置項(xiàng),并將其保存到配置文件中。 -
config:一個(gè)Config類的實(shí)例,用于訪問(wèn)和修改配置項(xiàng)。
該程序的主要功能是讀取和寫(xiě)入配置文件,通過(guò)調(diào)用get_setting和set_setting方法來(lái)獲取和設(shè)置配置項(xiàng)的值。配置文件的格式是JSON。
5.3 constants.py
class RubiksCube:
def __init__(self):
self.root_dir = os.path.dirname(os.path.abspath(__file__))
self.color_placeholder = (150, 150, 150)
self.locales = {
'de': 'Deutsch',
'hu': 'Hungarian',
'fr': 'French',
'en': 'English',
'nl': 'Nederlands',
'es': 'Spanish',
'zh': '簡(jiǎn)體中文',
}
self.mini_sticker_area_tile_size = 14
self.mini_sticker_area_tile_gap = 2
self.mini_sticker_area_offset = 20
self.sticker_area_tile_size = 30
self.sticker_area_tile_gap = 4
self.sticker_area_offset = 20
self.sticker_contour_color = (36, 255, 12)
self.calibrate_mode_key = 'c'
self.switch_language_key = 'l'
self.text_size = 18
self.cube_palette = 'cube_palette'
self.errors = {
'incorrectly_scanned': 1,
'already_solved': 2
}
這個(gè)程序文件名為constants.py,它包含了一些常量的定義。
首先,程序?qū)肓薿s模塊,并定義了一個(gè)全局變量ROOT_DIR,用于表示程序文件所在的根目錄。
接下來(lái),定義了一些顏色常量,如COLOR_PLACEHOLDER,表示一個(gè)灰色的占位符。
然后,定義了一個(gè)國(guó)際化的常量LOCALES,它是一個(gè)字典,包含了不同語(yǔ)言的鍵值對(duì),如'zh'表示簡(jiǎn)體中文。
接下來(lái),定義了一些與相機(jī)接口相關(guān)的常量,如MINI_STICKER_AREA_TILE_SIZE表示迷你貼紙區(qū)域的瓦片大小,STICKER_CONTOUR_COLOR表示貼紙輪廓的顏色等。
然后,定義了一個(gè)配置相關(guān)的常量CUBE_PALETTE,表示魔方的調(diào)色板。
最后,定義了一些應(yīng)用程序錯(cuò)誤的常量,如E_INCORRECTLY_SCANNED表示掃描錯(cuò)誤,E_ALREADY_SOLVED表示已經(jīng)解決等。
5.4 helpers.py
class ColorUtils:
@staticmethod
def get_next_locale(locale):
"""Cycle through the locales and get the next locale."""
keys = list(LOCALES.keys())
index = keys.index(locale)
if index + 1 >= len(keys):
return keys[0]
return keys[index + 1]
@staticmethod
def bgr2lab(inputColor):
"""Convert BGR to LAB."""
# Convert BGR to RGB
inputColor = (inputColor[2], inputColor[1], inputColor[0])
num = 0
RGB = [0, 0, 0]
for value in inputColor:
value = float(value) / 255
if value > 0.04045:
value = ( ( value + 0.055 ) / 1.055 ) ** 2.4
else:
value = value / 12.92
RGB[num] = value * 100
num = num + 1
XYZ = [0, 0, 0,]
X = RGB [0] * 0.4124 + RGB [1] * 0.3576 + RGB [2] * 0.1805
Y = RGB [0] * 0.2126 + RGB [1] * 0.7152 + RGB [2] * 0.0722
Z = RGB [0] * 0.0193 + RGB [1] * 0.1192 + RGB [2] * 0.9505
XYZ[ 0 ] = round( X, 4 )
XYZ[ 1 ] = round( Y, 4 )
XYZ[ 2 ] = round( Z, 4 )
XYZ[ 0 ] = float( XYZ[ 0 ] ) / 95.047 # ref_X = 95.047 Observer= 2°, Illuminant= D65
XYZ[ 1 ] = float( XYZ[ 1 ] ) / 100.0 # ref_Y = 100.000
XYZ[ 2 ] = float( XYZ[ 2 ] ) / 108.883 # ref_Z = 108.883
num = 0
for value in XYZ:
if value > 0.008856:
value = value ** ( 0.3333333333333333 )
else :
value = ( 7.787 * value ) + ( 16 / 116 )
XYZ[num] = value
num = num + 1
Lab = [0, 0, 0]
L = ( 116 * XYZ[ 1 ] ) - 16
a = 500 * ( XYZ[ 0 ] - XYZ[ 1 ] )
b = 200 * ( XYZ[ 1 ] - XYZ[ 2 ] )
Lab [ 0 ] = round( L, 4 )
Lab [ 1 ] = round( a, 4 )
Lab [ 2 ] = round( b, 4 )
return Lab
@staticmethod
def ciede2000(Lab_1, Lab_2):
"""Calculates CIEDE2000 color distance between two CIE L*a*b* colors."""
C_25_7 = 6103515625 # 25**7
L1, a1, b1 = Lab_1[0], Lab_1[1], Lab_1[2]
L2, a2, b2 = Lab_2[0], Lab_2[1], Lab_2[2]
C1 = math.sqrt(a1**2 + b1**2)
C2 = math.sqrt(a2**2 + b2**2)
C_ave = (C1 + C2) / 2
G = 0.5 * (1 - math.sqrt(C_ave**7 / (C_ave**7 + C_25_7)))
L1_, L2_ = L1, L2
a1_, a2_ = (1 + G) * a1, (1 + G) * a2
b1_, b2_ = b1, b2
C1_ = math.sqrt(a1_**2 + b1_**2)
C2_ = math.sqrt(a2_**2 + b2_**2)
if b1_ == 0 and a1_ == 0: h1_ = 0
elif a1_ >= 0: h1_ = math.atan2(b1_, a1_)
else: h1_ = math.atan2(b1_, a1_) + 2 * math.pi
if b2_ == 0 and a2_ == 0: h2_ = 0
elif a2_ >= 0: h2_ = math.atan2(b2_, a2_)
else: h2_ = math.atan2(b2_, a2_) + 2 * math.pi
dL_ = L2_ - L1_
dC_ = C2_ - C1_
dh_ = h2_ - h1_
if C1_ * C2_ == 0: dh_ = 0
elif dh_ > math.pi: dh_ -= 2 * math.pi
elif dh_ < -math.pi: dh_ += 2 * math.pi
dH_ = 2 * math.sqrt(C1_ * C2_) * math.sin(dh_ / 2)
L_ave = (L1_ + L2_) / 2
C_ave = (C1_ + C2_) / 2
_dh = abs(h1_ - h2_)
_sh = h1_ + h2_
C1C2 = C1_ * C2_
if _dh <= math.pi and C1C2 != 0: h_ave = (h1_ + h2_) / 2
elif _dh > math.pi and _sh < 2 * math.pi and C1C2 != 0: h_ave = (h1_ + h2_) / 2 + math.pi
elif _dh > math.pi and _sh >= 2 * math.pi and C1C2 != 0: h_ave = (h1_ + h2_) / 2 - math.pi
else: h_ave = h1_ + h2_
T = 1 - 0.17 * math.cos(h_ave - math.pi / 6) + 0.24 * math.cos(2 * h_ave) + 0.32 * math.cos(3 * h_ave + math.pi / 30) - 0.2 * math.cos(4 * h_ave - 63 * math.pi / 180)
h_ave_deg = h_ave * 180 / math.pi
if h_ave_deg < 0: h_ave_deg += 360
elif h_ave_deg > 360: h_ave_deg -= 360
dTheta = 30 * math.exp(-(((h_ave_deg - 275) / 25)**2))
R_C = 2 * math.sqrt(C_ave**7 / (C_ave**7 + C_25_7))
S_C = 1 + 0.045 * C_ave
S_H = 1 + 0.015 * C_ave * T
Lm50s = (L_ave - 50)**2
S_L = 1 + 0.015 * Lm50s / math.sqrt(20 + Lm50s)
R_T = -math.sin(dTheta * math.pi / 90) * R_C
k_L, k_C, k_H = 1, 1, 1
f_L = dL_ / k_L / S_L
f_C = dC_ / k_C / S_C
f_H = dH_ / k_H / S_H
dE_00 = math.sqrt(f_L**2 + f_C**2 + f_H**2 + R_T * f_C * f_H)
return dE_00
這個(gè)程序文件名為helpers.py,它包含了一些輔助函數(shù)和一個(gè)用于計(jì)算CIEDE2000顏色距離的函數(shù)。
其中的函數(shù)包括:
- get_next_locale(locale):循環(huán)遍歷LOCALES字典中的鍵,并返回下一個(gè)鍵。
- bgr2lab(inputColor):將BGR顏色轉(zhuǎn)換為L(zhǎng)AB顏色空間。
- ciede2000(Lab_1, Lab_2):計(jì)算兩個(gè)CIE Lab*顏色之間的CIEDE2000顏色距離。
這個(gè)程序文件還導(dǎo)入了math模塊和constants模塊中的LOCALES常量。
5.5 qbr.py
class Qbr:
def __init__(self, normalize):
self.normalize = normalize
def run(self):
"""The main function that will run the Qbr program."""
state = webcam.run()
# If we receive a number then it's an error code.
if isinstance(state, int) and state > 0:
self.print_E_and_exit(state)
try:
algorithm = kociemba.solve(state)
length = len(algorithm.split(' '))
except Exception:
self.print_E_and_exit(E_INCORRECTLY_SCANNED)
print(i18n.t('startingPosition'))
print(i18n.t('moves', moves=length))
print(i18n.t('solution', algorithm=algorithm))
if self.normalize:
for index, notation in enumerate(algorithm.split(' ')):
text = i18n.t('solveManual.{}'.format(notation))
print('{}. {}'.format(index + 1, text))
def print_E_and_exit(self, code):
"""Print an error message based on the code and exit the program."""
if code == E_INCORRECTLY_SCANNED:
print('\033[0;33m[{}] {}'.format(i18n.t('error'), i18n.t('haventScannedAllSides')))
print('{}\033[0m'.format(i18n.t('pleaseTryAgain')))
elif code == E_ALREADY_SOLVED:
print('\033[0;33m[{}] {}'.format(i18n.t('error'), i18n.t('cubeAlreadySolved')))
sys.exit(code)
這個(gè)程序文件名為qbr.py,是一個(gè)用Python編寫(xiě)的程序。該程序主要用于解決魔方。程序的功能如下:
- 導(dǎo)入了一些必要的模塊和庫(kù),包括sys、kociemba、argparse、video、i18n、os等。
- 設(shè)置了默認(rèn)的語(yǔ)言環(huán)境。
- 定義了一個(gè)Qbr類,該類有一個(gè)初始化方法和一個(gè)運(yùn)行方法。
- 運(yùn)行方法中,調(diào)用了webcam.run()函數(shù)獲取魔方的狀態(tài)。
- 根據(jù)獲取到的狀態(tài),使用kociemba.solve()函數(shù)求解魔方,并得到解法的長(zhǎng)度。
- 打印出魔方的初始狀態(tài)、解法的步驟和解法。
- 如果設(shè)置了normalize參數(shù),則將解法進(jìn)行歸一化處理,并打印出每一步的解法說(shuō)明。
- 定義了一個(gè)print_E_and_exit方法,用于打印錯(cuò)誤信息并退出程序。
- 在主程序中,定義了一個(gè)命令行參數(shù)解析器,并解析了-n參數(shù)。
- 創(chuàng)建一個(gè)Qbr對(duì)象,并調(diào)用其run()方法運(yùn)行程序。
6.系統(tǒng)整體結(jié)構(gòu)
整體功能和構(gòu)架概述:
該程序是一個(gè)使用YOLOv5模型進(jìn)行目標(biāo)檢測(cè)的圖形用戶界面應(yīng)用程序。它的主要功能是讀取視頻文件并對(duì)每一幀圖像進(jìn)行目標(biāo)檢測(cè),將檢測(cè)結(jié)果繪制在圖像上顯示給用戶。程序使用PyQt5構(gòu)建了圖形用戶界面,并通過(guò)調(diào)用YOLOv5模型進(jìn)行目標(biāo)檢測(cè)。
以下是每個(gè)文件的功能概述:
| 文件路徑 | 功能概述 |
|---|---|
| colordetection.py | 實(shí)現(xiàn)顏色檢測(cè)的類,包括獲取突出顏色、主要顏色等方法 |
| config.py | 處理配置文件的類,包括讀取和寫(xiě)入配置項(xiàng)的方法 |
| constants.py | 定義了一些常量,如顏色常量、配置常量等 |
| helpers.py | 包含一些輔助函數(shù),如獲取下一個(gè)語(yǔ)言環(huán)境、顏色轉(zhuǎn)換等 |
| qbr.py | 進(jìn)行魔方解決的程序 |
| ui.py | 創(chuàng)建和管理圖形用戶界面的類 |
| video.py | 處理視頻文件的類,包括讀取視頻幀、保存視頻等方法 |
| models_init_.py | 模型相關(guān)的初始化文件 |
| tools\activations.py | 激活函數(shù)相關(guān)的工具函數(shù) |
| tools\augmentations.py | 數(shù)據(jù)增強(qiáng)相關(guān)的工具函數(shù) |
| tools\autoanchor.py | 自動(dòng)錨框相關(guān)的工具函數(shù) |
| tools\autobatch.py | 自動(dòng)批處理相關(guān)的工具函數(shù) |
| tools\callbacks.py | 回調(diào)函數(shù)相關(guān)的工具函數(shù) |
| tools\datasets.py | 數(shù)據(jù)集相關(guān)的工具函數(shù) |
| tools\downloads.py | 下載相關(guān)的工具函數(shù) |
| tools\general.py | 通用工具函數(shù) |
| tools\loss.py | 損失函數(shù)相關(guān)的工具函數(shù) |
| tools\metrics.py | 度量指標(biāo)相關(guān)的工具函數(shù) |
| tools\plots.py | 繪圖相關(guān)的工具函數(shù) |
| tools\torch_utils.py | PyTorch相關(guān)的工具函數(shù) |
| tools_init_.py | 工具函數(shù)相關(guān)的初始化文件 |
| tools\aws\resume.py | AWS相關(guān)的恢復(fù)函數(shù) |
| tools\aws_init_.py | AWS相關(guān)的初始化文件 |
| tools\loggers_init_.py | 日志記錄器相關(guān)的初始化文件 |
| tools\loggers\wandb\log_dataset.py | 使用WandB記錄數(shù)據(jù)集的日志記錄器 |
| tools\loggers\wandb\sweep.py | 使用WandB進(jìn)行超參數(shù)搜索的日志記錄器 |
| tools\loggers\wandb\wandb_utils.py | 使用WandB的實(shí)用函數(shù) |
| tools\loggers\wandb_init_.py | 使用WandB的日志記錄器的初始化文件 |
| utils\activations.py | 激活函數(shù)相關(guān)的實(shí)用函數(shù) |
| utils\augmentations.py | 數(shù)據(jù)增強(qiáng)相關(guān)的實(shí)用函數(shù) |
| utils\autoanchor.py | 自動(dòng)錨框相關(guān)的實(shí)用函數(shù) |
| utils\autobatch.py | 自動(dòng)批處理相關(guān)的實(shí)用函數(shù) |
| utils\callbacks.py | 回調(diào)函數(shù)相關(guān)的實(shí)用函數(shù) |
| utils\datasets.py | 數(shù)據(jù)集相關(guān)的實(shí)用函數(shù) |
| utils\downloads.py | 下載相關(guān)的實(shí)用函數(shù) |
| utils\general.py | 通用實(shí)用函數(shù) |
| utils\loss.py | 損失函數(shù)相關(guān)的實(shí)用函數(shù) |
| utils\metrics.py | 度量指標(biāo)相關(guān)的實(shí)用函數(shù) |
| utils\plots.py | 繪圖相關(guān)的實(shí)用函數(shù) |
| utils\torch_utils.py | PyTorch相關(guān)的實(shí)用函數(shù) |
| utils_init_.py | 實(shí)用函數(shù)相關(guān)的初始化文件 |
| utils\aws\resume.py | AWS相關(guān)的恢復(fù)函數(shù) |
| utils\aws_init_.py | AWS相關(guān)的初始化文件 |
| utils\flask_rest_api\example_request.py | Flask REST API的示例請(qǐng)求 |
| utils\flask_rest_api\restapi.py | Flask REST API的實(shí)現(xiàn) |
| utils\loggers_init_.py | 日志記錄器相關(guān)的初始化文件 |
| utils\loggers\wandb\log_dataset.py | 使用WandB記錄數(shù)據(jù)集的日志記錄器 |
| utils\loggers\wandb\sweep.py | 使用WandB進(jìn)行超參數(shù)搜索的日志記錄器 |
| utils\loggers\wandb\wandb_utils.py | 使用WandB的實(shí)用函數(shù) |
| utils\loggers\wandb_init_.py | 使用WandB的日志記錄器的初始化文件 |
7.魔方的結(jié)構(gòu)
三階魔方是由54個(gè)小色塊組成的6面正方體。魔方核心是一個(gè)支撐上下前后左右6個(gè)方向的軸,外部由8個(gè)角塊,12個(gè)棱塊,6個(gè)中心色塊共計(jì)26個(gè)小正方體組成 32]。其中邊角方塊(角塊)可繞中心軸轉(zhuǎn)動(dòng),三面有顏色。邊緣方塊(棱塊)亦可繞中心軸轉(zhuǎn)動(dòng),兩面有顏色。中心色塊固定不動(dòng),只有一面有顏色。26個(gè)小正方體的著色面加起來(lái)有54面,可以說(shuō)魔方的狀態(tài)就是由54個(gè)小面的顏色排列決定的。魔方的幾何結(jié)構(gòu)如圖所示。

魔方著色有著默認(rèn)的國(guó)際標(biāo)準(zhǔn)即:左面是藍(lán)色,右面是綠色,上面是黃色,底面是白色,前面是紅色,后面是橙色,即藍(lán)色面和綠色面是左右對(duì)應(yīng)的,白色面和黃色面是上下相對(duì)的,紅色面和橙色面是前后對(duì)應(yīng)的,如圖所示。

8.圖像預(yù)處理
圖像預(yù)處理是一種相對(duì)于圖像識(shí)別,圖像分析和圖像理解的預(yù)處理措施。它也可以被視為初始獲取圖像的增強(qiáng),目的是使用一系列方法來(lái)提高圖像效果或?qū)D像格式轉(zhuǎn)換為更適合計(jì)算機(jī)或人分析的形式[2]。簡(jiǎn)而言之,它突出了有用信息并消除了干擾信息。
參考該博客的預(yù)處理方法,魔方圖片在獲取的過(guò)程中,由于光照,外界環(huán)境,內(nèi)部電路等因素的影響,容易造成魔方圖片的模糊、輪廓不清楚和畸變等情況,這種圖像質(zhì)量下降的現(xiàn)象稱之為圖像的退化,而那些影響因素稱之為圖像噪聲[3]。圖片的退化對(duì)魔方RGB值的提取有很大的干擾,進(jìn)而降低了之后顏色識(shí)別的成功率。因此,為了改變這種情況,必須對(duì)原始圖像進(jìn)行預(yù)處理,去除圖像噪聲,提高魔方圖像的質(zhì)量。
去除圖像噪聲一般采用濾波處理,而濾波器的選擇由噪聲的類型和圖像的幾何特點(diǎn)來(lái)決定。經(jīng)過(guò)大量的實(shí)驗(yàn)觀察和對(duì)比,發(fā)現(xiàn)魔方圖片的噪聲屬于離散噪聲。魔方顏色較為復(fù)雜,白色色塊與底色相同而且黃色與橙色對(duì)比不甚明顯[4]。綜合以上因素,為了最大程度上保留圖像中的信息量,本文選擇中值濾波的方法去除圖像噪聲。
中值濾波是一種應(yīng)用于抑制噪聲的非線性信號(hào)處理技術(shù)?;驹硎菍⒁粋€(gè)像素點(diǎn)的灰度值等同于相鄰窗口中所有像素點(diǎn)灰度值的中值,以使周圍的像素值更接近真實(shí)值,從而消除孤立的噪聲點(diǎn)[4]。

9.區(qū)域生長(zhǎng)算法
參考該博客給出的代碼,要想確定打亂的魔方的顏色分布,首先就要通過(guò)圖像分割劃分魔方的各個(gè)色塊,從而提取色塊的RGB值。目前技術(shù)成熟的圖像分割方法有以下幾種:基于區(qū)域的分割方法、基于閾值的分割方法、基于特定理論的分割方法以及基于邊緣的分割方法等l5]。由于魔方在照片中的位置大致不變而且區(qū)域不大,因此本文圖像分割采用基于區(qū)域分割的區(qū)域成長(zhǎng)方法。
區(qū)域生長(zhǎng)的基本原理是:以事先設(shè)定好的種子像素為生長(zhǎng)的起始點(diǎn),然后找出種子像素周圍的鄰域中具有與種子像素相似或相同屬性的像素(根據(jù)一些預(yù)定的增長(zhǎng)或要確定的相似性標(biāo)準(zhǔn))與種子像素組成新的的區(qū)域。之后將加入的新像素視為新的種子像素重復(fù)上述過(guò)程,直到達(dá)到設(shè)定標(biāo)準(zhǔn)為止,這樣一個(gè)區(qū)域就長(zhǎng)成了[6]。
區(qū)域生長(zhǎng)需要選擇一組可以精確表示所需區(qū)域的種子像素,確定生長(zhǎng)過(guò)程中的相似性標(biāo)準(zhǔn),并制定相應(yīng)條件或準(zhǔn)則以停止種子的生長(zhǎng)。相似性標(biāo)準(zhǔn)可以是諸如顏色紋理、灰度、梯度等特征。所選種子像素可以是單個(gè)像素,也可以是包含多個(gè)像素的小區(qū)域。大多數(shù)區(qū)域增長(zhǎng)準(zhǔn)則都使用圖像的局部性質(zhì),也可以根據(jù)不同的原則制定生長(zhǎng)準(zhǔn)則,并且不同的生長(zhǎng)準(zhǔn)則可能會(huì)影響區(qū)域增長(zhǎng)的過(guò)程。區(qū)域生長(zhǎng)的優(yōu)點(diǎn)是計(jì)算簡(jiǎn)單,對(duì)于均勻的連通目標(biāo)有更好的分割效果。它的缺點(diǎn)是對(duì)噪聲敏感,而且需要人為地確定種子位置。另外,它是一種串行算法。當(dāng)目標(biāo)較大時(shí),分割速度較慢。因此在設(shè)計(jì)算法時(shí),需要盡可能地提高效率。

10.系統(tǒng)整合

參考博客《Python+OpenCV魔方識(shí)別系統(tǒng)(源碼和部署教程)》
11.參考文獻(xiàn)
[1]李博男,林凡.基于曲率的指尖檢測(cè)方法[J].南京航空航天大學(xué)學(xué)報(bào).2012,(4).DOI:10.3969/j.issn.1005-2615.2012.04.026.
[2]楊揚(yáng),程楠楠,張萌萌.基于平均鄰域最大化的手勢(shì)識(shí)別方法研究[J].計(jì)算機(jī)工程.2012,(9).DOI:10.3969/j.issn.1000-3428.2012.09.006.
[3]王守磊,朱民耀,陸小鋒,等.一種基于方向直方圖的嵌入式手勢(shì)識(shí)別系統(tǒng)[J].電視技術(shù).2012,(15).DOI:10.3969/j.issn.1002-8692.2012.15.038.
[4]張登康,郭太良,姚劍敏,等.改進(jìn)膚色識(shí)別參量和輪廓特征相結(jié)合的指尖檢測(cè)[J].光電子技術(shù).2012,(3).DOI:10.3969/j.issn.1005-488X.2012.03.009.
[5]翁漢良,戰(zhàn)蔭偉.基于視覺(jué)的多特征手勢(shì)識(shí)別[J].計(jì)算機(jī)工程與科學(xué).2012,(2).DOI:10.3969/j.issn.1007-130X.2012.02.023.
[6]朱正禮,趙春霞,侯迎坤,等.基于多特征的旋轉(zhuǎn)不變紋理圖像檢索[J].南京理工大學(xué)學(xué)報(bào)(自然科學(xué)版).2012,(3).DOI:10.3969/j.issn.1005-9830.2012.03.001.
[7]曹雛清,李瑞峰,趙立軍.基于深度圖像技術(shù)的手勢(shì)識(shí)別方法[J].計(jì)算機(jī)工程.2012,(8).DOI:10.3969/j.issn.1000-3428.2012.08.006.
[8]李曉娟,楊唐文,阮秋琦,等.基于輪廓線特征的三維人臉識(shí)別改進(jìn)算法[J].鐵道學(xué)報(bào).2012,(1).DOI:10.3969/j.issn.1001-8360.2012.01.007.
[9]陳啟軍,朱振嬌,顧爽.基于傅立葉描述子和HMM的手勢(shì)識(shí)別[J].控制工程.2012,(4).DOI:10.3969/j.issn.1671-7848.2012.04.022.
[10]王小華,徐蕙素,吳海虹.基于YCgCr顏色空間的不良圖像膚色檢測(cè)[J].計(jì)算機(jī)應(yīng)用與軟件.2011,(4).DOI:10.3969/j.issn.1000-386X.2011.04.044.