158 How can something be so nice?
178 Yet so shocking, yet so nice.
321 How can something be so new?
403 Yet so known but yet so new?
466 Ohh, one two, three, the time has gone.
494 Problematic things undone.
585 How an something be so cruel?
640 Yet so warm but yet so cruel?
992 Try to find from a different sight,
1053 Get to choose where to look back,
1120 Resolve what others can't do for now...
1324 What a beautiful way to fix all wrong things.
1383 Evolve future generations of work teams.
1562 But tell me why's that fear of yours,
1633 'Cause you know it is going to work... (keep it up)
1757 Let's start from now, stay tuned, you're half way through!
1834 Break it, crash it, take it farther
1956 Making something even smarter.
1993 Do it, start it, make it happen,
2079 Stab in statements screaming louder.
2119 How can something be so nice?
2207 Yet so shocking, yet so nice.
2261 How can something be so new?
2334 Yet so known but yet...
2424 IT'S SOMETHING NEW
2650 IT'S SOMETHING NEW
178 Yet so shocking, yet so nice.
321 How can something be so new?
403 Yet so known but yet so new?
466 Ohh, one two, three, the time has gone.
494 Problematic things undone.
585 How an something be so cruel?
640 Yet so warm but yet so cruel?
992 Try to find from a different sight,
1053 Get to choose where to look back,
1120 Resolve what others can't do for now...
1324 What a beautiful way to fix all wrong things.
1383 Evolve future generations of work teams.
1562 But tell me why's that fear of yours,
1633 'Cause you know it is going to work... (keep it up)
1757 Let's start from now, stay tuned, you're half way through!
1834 Break it, crash it, take it farther
1956 Making something even smarter.
1993 Do it, start it, make it happen,
2079 Stab in statements screaming louder.
2119 How can something be so nice?
2207 Yet so shocking, yet so nice.
2261 How can something be so new?
2334 Yet so known but yet...
2424 IT'S SOMETHING NEW
2650 IT'S SOMETHING NEW
duangsuse::Echo
现在内存的问题解决了,这个图形处理算法可是有大问题……
https://github.com/duangsuse/extract-subtitles/blob/master/extract_subtitles.py#L55-L68
总结下,内存问题是用 chunked processing 解决的。
我简化了程序,梳理了下数据流,把合适的部分从靠
定义两个辅助 generator:
这段原程序就是之前会导致内存不够用的:
接下来就是重构依赖它的依赖操作了,实际上只需要一个子程序来利用
然后,
但是,这种操作应该怎么运行(并且拿回,准确的说是「拼接」回结果)呢 🤔
刚才有说,直接贴代码:
这就是我解决
总结下,内存问题是用 chunked processing 解决的。
我简化了程序,梳理了下数据流,把合适的部分从靠
list 改成了用 generator(接着可以 hack 的地方就多了)定义两个辅助 generator:
def chunked(n, xs):
while True:
try: #< must return when inner gen finished
first = next(xs)
except StopIteration: return
chunk = islice(xs, n)
yield chain((first,) , chunk)
def collect2(selector2, xs):
bs, cs = [], []
for x in xs:
b, c = selector2(x)
bs.append(b); cs.append(c)
return (bs, cs) 这段原程序就是之前会导致内存不够用的:
def solveFrameDifferences(self, cap: VideoCapture, crop: Rect, fold) -> Frame: #!generator
于是我移除了没损失信息量的对象,给它重构成 yield Frame(index, curr_frame, count) 的形式接下来就是重构依赖它的依赖操作了,实际上只需要一个子程序来利用
collect2 来部分(按chunk)地执行计算,我这里直接加在原来依赖 list 版以上函数的操作里: def ocrWithLocalMaxima(self, frames, on_new_subtitle) -> array: 然后,
frame_list, frame_diffs = collect2(lambda it: (it, it.value), frames)接下来的操作和以往无二,但再也不会内存不足了(只要你不关掉GC,相当于手动把视频切成 N 块再逐个操作,哈哈)。 🥳
self.onFrameList(frame_list) 但是,这种操作应该怎么运行(并且拿回,准确的说是「拼接」回结果)呢 🤔
刚才有说,直接贴代码:
processChunk = lambda it: self.ocrWithLocalMaxima(it, on_new_subtitle)
diff_array_parts = map(processChunk, chunked(self.chunk_size, frames))
diff_array = reduce(lambda a, b: concatenate(array([a, b])), diff_array_parts) 这就是我解决
opencv-python 处理内存不足问题的全部细节。 🙂 #Python #Learn #DIP #CVGitHub
duangsuse/extract-subtitles
Extract Subtitles From Video 视频字幕提取 帧间差分法识别关键帧 OCR识别 - duangsuse/extract-subtitles
duangsuse::Echo
https://github.com/duangsuse/extract-subtitles/blob/master/extract_subtitles.py#L55-L68 总结下,内存问题是用 chunked processing 解决的。 我简化了程序,梳理了下数据流,把合适的部分从靠 list 改成了用 generator(接着可以 hack 的地方就多了) 定义两个辅助 generator: def chunked(n, xs): while True: try: #< must return…
我正在考虑添加一个能给『字幕分时段在不同位置出现的视频打轴』的脚本或者 Qt 应用 🤔
打完轴以后,就变成一个
还有一个能把
第一个应用有一个关键视图/交互需要实现:图像选区框
我已经想好了怎么同时支持绘制和事件监听(整个给做成 Widget,然后用 move 和 resize),只需要先学学 Qt 基础 🤔
打完轴以后,就变成一个
TreeSet ,然后我可以 findMaxLT 来取到最近的 crop 区域还有一个能把
extract_subtitles 输出自动检查合并到 ASS 这种 subtitles 格式的脚本,依然可以用到 zipWithNext 第一个应用有一个关键视图/交互需要实现:图像选区框
我已经想好了怎么同时支持绘制和事件监听(整个给做成 Widget,然后用 move 和 resize),只需要先学学 Qt 基础 🤔
Forwarded from いっぽから
https://dungeon-lab.com/e-stim-unit.html 卧槽可以App编程的estim device 好奇是电荷泵还是电流源 #NSFW
duangsuse::Echo
我正在考虑添加一个能给『字幕分时段在不同位置出现的视频打轴』的脚本或者 Qt 应用 🤔 打完轴以后,就变成一个 TreeSet ,然后我可以 findMaxLT 来取到最近的 crop 区域 还有一个能把 extract_subtitles 输出自动检查合并到 ASS 这种 subtitles 格式的脚本,依然可以用到 zipWithNext 第一个应用有一个关键视图/交互需要实现:图像选区框 我已经想好了怎么同时支持绘制和事件监听(整个给做成 Widget,然后用 move 和 resize),只需要先学学…
🤔 刚才我和 duangsuse 讨论了一下关于这个框选绘制的问题,
Qt 提供了信号/插槽机制以支持 message/view update/async 什么的,反正是个类的实例都可以有,于是考虑了
本来说的是可以添加一个状态(
可是如果要那样的话就不能正常响应用户交互了,其实这一个状态即便不用 Qt 而自己维护,也是必须的(只不过是作为其它函数的变量,按以上
毕竟不能为 Qt Object 添加动态(带闭包)监听,所以静态类型监听的话,只能把
接着关于具体的绘制我想了想,大致上可以用 layout + 四个子 Widget(LRUD 四边),或者作为一个整体绘制和 handle message (就需要区间判定了)
这么一想我就觉得…… 要维护那么多子 Widget 的话还是整体 top_y0, top_y1, bot_y0, bot_y1 什么的好
Qt 提供了信号/插槽机制以支持 message/view update/async 什么的,反正是个类的实例都可以有,于是考虑了
SelectionWidget(QPoint, QArea) 之类的架构器,还有一个初始的 enterResize() 操作本来说的是可以添加一个状态(
isRunResize 或者 isResizing),可是又提出了可以直接在 enterResize() 函数里更新视图大小(隐含的信息是阻塞在这个 call frame 里,然后 view update 也写死在里面)可是如果要那样的话就不能正常响应用户交互了,其实这一个状态即便不用 Qt 而自己维护,也是必须的(只不过是作为其它函数的变量,按以上
enterResize() 的时候绑定 mouse move 到 pos-/resize 其实是用调用栈存状态)毕竟不能为 Qt Object 添加动态(带闭包)监听,所以静态类型监听的话,只能把
isRunResize 写在里面,如此。接着关于具体的绘制我想了想,大致上可以用 layout + 四个子 Widget(LRUD 四边),或者作为一个整体绘制和 handle message (就需要区间判定了)
这么一想我就觉得…… 要维护那么多子 Widget 的话还是整体 top_y0, top_y1, bot_y0, bot_y1 什么的好
duangsuse::Echo
Python 内建的 argparse 模块太垃圾了,居然不支持一个选项两个项目 -op a b 的……
就因为这个模块是这样,就不能弄一个配置(crop: dict)处理多个不同 crop 的视频了(需要调用更多次才可以
但依然可以处理连套的视频,比如 TV Show 什么的
我这里有半套《爱情公寓》,待会写好了 subtitle2ass 再来看看
但依然可以处理连套的视频,比如 TV Show 什么的
我这里有半套《爱情公寓》,待会写好了 subtitle2ass 再来看看
https://pypi.org/project/srt/ …… 我看我还是做抽象一点 🤔不就是个 subtitle 时间轴嘛
PyPI
srt
A tiny library for parsing, modifying, and composing SRT files.
🤔 #Python #code 之前我看 SCP-079 群里那个翻译的实现(用的不是 Qt 封的 translate 什么的),他们是这个格式
{
}
第一次看到的时候,我觉得好高大上啊,而且以为他们肯定重载了 and / or operator 的语义,甚至在脑内自动意淫出了一个递归结构:
(后来发现递归的其实是一个链表)
然后我编写了一个查表算法(后来被证实不过是链表查找,开始我还以为是高大上的递归结构呢):
再后来,我发现这整个其实都是谎话—— 使用这种方式意味着 SCP-079 用 zh_cn: bool 作为参数,然后利用 truthy/falsey value 的动态类型特性,去 "Hack" 一个 EDSL(embedded domain specific lang.)……
如果要缓存,结果是一个关于
{
"admin": (zh_cn and "管理员") or "Administrator" }
第一次看到的时候,我觉得好高大上啊,而且以为他们肯定重载了 and / or operator 的语义,甚至在脑内自动意淫出了一个递归结构:
(后来发现递归的其实是一个链表)
class Translation:
def __init__(self, lang, text):
self.lang, self.text = lang, text
class Link:
def __init__(self, head, tail):
self.head, self.tail = head, tail
def _and(lang, text): return Translation(lang, text)
def _or(translation, tail): return Link(translation, tail) 然后我编写了一个查表算法(后来被证实不过是链表查找,开始我还以为是高大上的递归结构呢):
def getTranslation(key, lang):
current = translations[key]
while current != None:
if current.head.lang == lang: return current.head.text
raise KeyError(f"undefined {key} for {lang}") 再后来,我发现这整个其实都是谎话—— 使用这种方式意味着 SCP-079 用 zh_cn: bool 作为参数,然后利用 truthy/falsey value 的动态类型特性,去 "Hack" 一个 EDSL(embedded domain specific lang.)……
如果要缓存,结果是一个关于
zh_cn 之类的 bool 的 Map<LangID, Map<TextID, Text>>
我看还不如这样吧:{
"admin": i18n(zh_cn="管理员", en_us="Administrator")
} def i18n(**kwargs):
require(all(map(languages.__contains__, map(dict.key, kwargs) )), "unsupported language")
return kwargs (草,这么直白太过分……)