В моем проекте с открытым исходным кодом https://github.com/WolfgangFahl/play-chess-with-a-webcam я использую класс Warp (см. https://github.com/WolfgangFahl/play-chess-with-a-webcam/blob/master/src/WebApp.py и фрагмент кода ниже), чтобы отслеживать точки деформации для шахматной доски. Идея состоит в том, что пользователь нажимает одну точку трапеции за другой, пока не станет известна позиция шахматной доски на изображении. Затем изображение «деформируется» соответственно. Чтобы вернуться к не деформированному изображению, другой щелчок сбросит деформацию.
Эта логика реализована путем подсчета количества точек, уже добавленных в «список точек». По умолчанию для списка точек задано пустое значение, но его также можно указать с помощью командной строки.
это соответствующий фрагмент конструктора:
def __init__(self,pointList=[],rotation=0,bgrColor=(0, 255, 0)):
self.pointList = pointList
self.updatePoints()
Теперь имеется тестирование для тестирования этого класса. см. https://github.com/WolfgangFahl/play-chess-with-a-webcam/blob/master/src/test_Warp.py и приведенный ниже код.
При непосредственном запуске этого кода
python3 test_Warp.py
код успешно работает на разных машинах, версиях python3.x и travis. Но если я запускаю весь набор тестов проекта
scripts/test
Поведение зависит от того, имеет ли функция getTestWarp:
def getTestWarp():
warp=Warp([])
, которая работает. Или:
def getTestWarp():
warp=Warp()
, что приводит к сбою тестового набора, если ранее выполнялись другие тесты. Таким образом, контекст имеет значение.
Как это может быть?
Является ли это ошибкой или ожидаемым поведением и может быть объяснено каким-то специфическим для Python способом обработки параметров по умолчанию иатрибуты экземпляра?
Класс деформации
class Warp(YamlAbleMixin,JsonAbleMixin):
""" holds the trapezoid points to be use for warping an image take from a peculiar angle """
# construct me from the given setting
def __init__(self,pointList=[],rotation=0,bgrColor=(0, 255, 0)):
self.rotation=rotation
self.bgrColor=bgrColor
self.pointList = pointList
self.updatePoints()
def rotate(self,angle):
self.rotation=self.rotation+angle
if self.rotation>=360:
self.rotation=self.rotation % 360
def updatePoints(self):
pointLen=len(self.pointList)
if pointLen==0:
self.points=None
else:
self.points=np.array(self.pointList)
self.warping=pointLen==4
def addPoint(self,px,py):
""" add a point with the given px,py coordinate
to the warp points make sure we have a maximum of 4 warpPoints if warppoints are complete when adding reset them
this allows to support click UIs that need an unwarped image before setting new warp points.
px,py is irrelevant for reset """
if len(self.pointList)>=4:
self.pointList=[]
else:
self.pointList.append([px,py])
self.updatePoints()
test_Warp.py
def getTestWarp():
warp=Warp([])
warp.addPoint(678,25)
warp.addPoint(1406,270)
warp.addPoint(1136,1048)
warp.addPoint(236,666)
return warp
def test_WarpPoints():
warp=getTestWarp()
print (warp.pointList)
print (warp.points)
assert warp.pointList==[[678, 25], [1406, 270], [1136, 1048], [236, 666]]
# simulate clear click
warp.addPoint(0,0)
warp.addPoint(679,25)
warp.addPoint(1408,270)
warp.addPoint(1136,1049)
warp.addPoint(236,667)
print (warp.pointList)
print (warp.points)
assert warp.pointList==[[679, 25], [1408, 270], [1136, 1049], [236, 667]]
test_WarpPoints()