Skip to content

Commit dfc8dd7

Browse files
committed
md: support MagiaExedra
1 parent f70fcfb commit dfc8dd7

File tree

5 files changed

+132
-0
lines changed

5 files changed

+132
-0
lines changed

ConfigSchema.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
"enum": [
110110
"mr",
111111
"mr-s0",
112+
"md",
112113
"lcb",
113114
"lcb-mech",
114115
"pkm",
@@ -192,6 +193,25 @@
192193
}
193194
}
194195
},
196+
"md": {
197+
"description": "MagiaExedra quest video",
198+
"type": "object",
199+
"patternProperties": {
200+
".*": {
201+
"description": "a preset for strategy md",
202+
"type": "object",
203+
"properties": {
204+
"dialogRect": {
205+
"$ref": "#/$defs/ratioRectangle"
206+
}
207+
},
208+
"required": [
209+
"dialogRect"
210+
],
211+
"additionalProperties": false
212+
}
213+
}
214+
},
195215
"lcb": {
196216
"description": "LimbusCompany quest video",
197217
"type": "object",

IR.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ def apply(self, fpir: FPIR):
138138
else:
139139
framePoint.setFlag(self.dstFlag, self.inverse)
140140

141+
class FPIRPassShift(FPIRPass):
142+
def __init__(self, tgtFlag: AbstractFlagIndex, refFlag: AbstractFlagIndex, shift: int, padding: typing.Any):
143+
self.tgtFlag: AbstractFlagIndex = tgtFlag
144+
self.refFlag: AbstractFlagIndex = refFlag
145+
self.shift: int = shift
146+
self.padding: typing.Any = padding
147+
148+
def apply(self, fpir: FPIR):
149+
for iTgt, framePoint in enumerate(fpir.framePoints):
150+
iSrc = iTgt - self.shift
151+
if iSrc < 0 or iSrc >= len(fpir.framePoints):
152+
framePoint.setFlag(self.tgtFlag, self.padding)
153+
else:
154+
framePoint.setFlag(self.tgtFlag, fpir.framePoints[iSrc].getFlag(self.refFlag))
155+
141156
class FPIRPassFunctional(FPIRPass):
142157
def __init__(self, func: typing.Callable[[FPIR], typing.Any]):
143158
self.func = func

MagiaTimeline.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from Util import *
1818
from Strategies.MagirecoStrategy import *
1919
from Strategies.MagirecoScene0Strategy import *
20+
from Strategies.MadodoraStrategy import *
2021
from Strategies.LimbusCompanyStrategy import *
2122
from Strategies.LimbusCompanyMechanicsStrategy import *
2223
from Strategies.PokemonEmeraldStrategy import *
@@ -83,6 +84,8 @@ def main():
8384
strategy = MagirecoStrategy(strategyConfig, contentRect)
8485
elif config["strategy"] == "mr-s0":
8586
strategy = MagirecoScene0Strategy(strategyConfig, contentRect)
87+
elif config["strategy"] == "md":
88+
strategy = MadodoraStrategy(strategyConfig, contentRect)
8689
elif config["strategy"] == "lcb":
8790
strategy = LimbusCompanyStrategy(strategyConfig, contentRect)
8891
elif config["strategy"] == "lcb-mech":

Strategies/MadodoraStrategy.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import typing
2+
import enum
3+
import collections
4+
5+
from Util import *
6+
from Strategies.AbstractStrategy import *
7+
from AbstractFlagIndex import *
8+
from Rectangle import *
9+
from IR import *
10+
11+
class MadodoraStrategy(AbstractFramewiseStrategy):
12+
class FlagIndex(AbstractFlagIndex):
13+
Dialog = enum.auto()
14+
DialogFuture = enum.auto()
15+
DialogBg = enum.auto()
16+
DialogText = enum.auto()
17+
18+
@classmethod
19+
def getDefaultFlagsImpl(cls) -> typing.List[typing.Any]:
20+
return [False] * cls.getNum()
21+
22+
def __init__(self, config: dict, contentRect: AbstractRectangle) -> None:
23+
AbstractStrategy.__init__(self, contentRect)
24+
self.rectangles: collections.OrderedDict[str, AbstractRectangle] = collections.OrderedDict()
25+
for k, v in config.items():
26+
self.rectangles[k] = RatioRectangle(contentRect, *v)
27+
28+
self.dialogRect = self.rectangles["dialogRect"]
29+
30+
self.cvPasses = [self.cvPassDialog]
31+
32+
self.fpirPasses = collections.OrderedDict()
33+
self.fpirPasses["fpirPassDialogFuture"] = FPIRPassShift(MadodoraStrategy.FlagIndex.DialogFuture, MadodoraStrategy.FlagIndex.Dialog, -30, False)
34+
self.fpirPasses["fpirPassDialogRefine"] = FPIRPassFramewiseFunctional(
35+
lambda framePoint: framePoint.setFlag(
36+
MadodoraStrategy.FlagIndex.Dialog,
37+
framePoint.getFlag(MadodoraStrategy.FlagIndex.Dialog)
38+
or framePoint.getFlag(MadodoraStrategy.FlagIndex.DialogFuture) and framePoint.getFlag(MadodoraStrategy.FlagIndex.DialogBg)
39+
)
40+
)
41+
self.fpirPasses["fpirPassRemoveNoiseDialogTrue"] = FPIRPassBooleanRemoveNoise(MadodoraStrategy.FlagIndex.Dialog, True, 10)
42+
43+
self.fpirToIirPasses = collections.OrderedDict()
44+
self.fpirToIirPasses["fpirPassBuildIntervals"] = FPIRPassBooleanBuildIntervals(
45+
MadodoraStrategy.FlagIndex.Dialog,
46+
)
47+
48+
self.iirPasses = collections.OrderedDict()
49+
self.iirPasses["iirPassFillGapDialog"] = IIRPassFillGap(MadodoraStrategy.FlagIndex.Dialog, 300, 0.0)
50+
51+
self.logfile = open("madodora.log", "w")
52+
53+
54+
@classmethod
55+
def getFlagIndexType(cls) -> typing.Type[AbstractFlagIndex]:
56+
return cls.FlagIndex
57+
58+
def getRectangles(self) -> collections.OrderedDict[str, AbstractRectangle]:
59+
return self.rectangles
60+
61+
def getCvPasses(self) -> typing.List[typing.Callable[[cv.Mat, FramePoint], bool]]:
62+
return self.cvPasses
63+
64+
def getFpirPasses(self) -> collections.OrderedDict[str, FPIRPass]:
65+
return self.fpirPasses
66+
67+
def getFpirToIirPasses(self) -> collections.OrderedDict[str, FPIRPassBuildIntervals]:
68+
return self.fpirToIirPasses
69+
70+
def getIirPasses(self) -> collections.OrderedDict[str, IIRPass]:
71+
return self.iirPasses
72+
73+
def cvPassDialog(self, frame: cv.Mat, framePoint: FramePoint) -> bool:
74+
roiDialog = self.dialogRect.cutRoiToUmat(frame)
75+
roiDialogGray = cv.cvtColor(roiDialog, cv.COLOR_BGR2GRAY)
76+
_, roiDialogTextBin = cv.threshold(roiDialogGray, 192, 255, cv.THRESH_BINARY)
77+
_, roiDialogBgBin = cv.threshold(roiDialogGray, 70, 255, cv.THRESH_BINARY)
78+
meanDialogTextBin: float = cv.mean(roiDialogTextBin)[0]
79+
meanDialogBgBin: float = cv.mean(roiDialogBgBin)[0]
80+
hasDialogBg: bool = meanDialogBgBin < 20 and meanDialogBgBin > 0.1
81+
hasDialogText: bool = meanDialogTextBin < 10 and meanDialogTextBin > 0.1
82+
83+
isValidDialog = hasDialogBg and hasDialogText
84+
85+
framePoint.setFlag(MadodoraStrategy.FlagIndex.Dialog, isValidDialog)
86+
framePoint.setFlag(MadodoraStrategy.FlagIndex.DialogBg, hasDialogBg)
87+
framePoint.setFlag(MadodoraStrategy.FlagIndex.DialogText, hasDialogText)
88+
89+
return isValidDialog

config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ mr-s0:
116116
dialogRect: [0.32, 0.68, 0.76, 0.96]
117117
blackscreenRect: [0.15, 0.85, 0.00, 1.00]
118118

119+
# MagiaExedra quest video
120+
md:
121+
default:
122+
dialogRect: [0.25, 0.75, 0.80, 1.00]
123+
119124
# LimbusCompany quest video
120125
lcb:
121126
default:

0 commit comments

Comments
 (0)