liuhongrun2022 发表于 2023-9-10 19:19:18

print问题

这段代码,每打印一帧就会清除,而我用的又是多进程,非常晃,时间长了眼睛容易瞎
就是下面这样(真实情况比gif更晃):
https://www.123pan.com/s/Hhs8Vv-RyCRh.html
import cv2
import os
from multiprocessing import Pool

def process_frame(frame):
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    resized_frame = cv2.resize(gray_frame, (160, 48))
    lines = []
    for row in resized_frame:
      line = ''.join(['█' if pixel >= 128 else ' ' for pixel in row])
      lines.append(line)
    return lines

if __name__ == '__main__':
    video = cv2.VideoCapture('1.mp4')
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    pool = Pool()# 创建进程池
    i = 0
    while True:
      ret, frame = video.read()
      if not ret:
            break

      result = pool.apply_async(process_frame, (frame,))# 异步调用process_frame函数
      lines = result.get()# 获取处理结果

      for line in lines:
            print(line)
      os.system("cls")

      i += 1
      print("已经打印的帧数:", i)
      print("总帧数:", total_frames)

    video.release()

isdkz 发表于 2023-9-10 19:19:28

这段代码每打印一帧就会清除,可以通过在控制台上打印 ANSI 转义序列来实现在同一位置上更新帧。以下是修改后的代码:

import cv2
import os
from multiprocessing import Pool

# ANSI 转义序列,用于在同一位置上更新帧
ERASE_LINE = '\x1b[2K'
CURSOR_UP_ONE = '\x1b[1A'

def process_frame(frame):
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    resized_frame = cv2.resize(gray_frame, (160, 48))
    lines = []
    for row in resized_frame:
      line = ''.join(['█' if pixel >= 128 else ' ' for pixel in row])
      lines.append(line)
    return lines

if __name__ == '__main__':
    video = cv2.VideoCapture('1.mp4')
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    pool = Pool()# 创建进程池
    i = 0
    while True:
      ret, frame = video.read()
      if not ret:
            break

      result = pool.apply_async(process_frame, (frame,))# 异步调用process_frame函数
      lines = result.get()# 获取处理结果

      # 在同一位置上更新帧
      for line in lines:
            print(ERASE_LINE + line)
      print(CURSOR_UP_ONE * len(lines), end='')

      i += 1
      print("已经打印的帧数:", i)
      print("总帧数:", total_frames)

    video.release()


在这个修改后的代码中,我们使用 ANSI 转义序列来实现在同一位置上更新帧。 ERASE_LINE变量用于清除当前行, CURSOR_UP_ONE变量用于将光标移动到上一行,以便在同一位置上更新帧。 print(CURSOR_UP_ONE * len(lines), end='')用于将光标移动到帧的第一行,以便下一帧能够在正确的位置上打印。

Mike_python小 发表于 2023-9-10 19:19:42

这段代码每打印一帧就会清除,导致在使用多进程时非常晃动,久而久之容易对眼睛造成伤害。为了解决这个问题,你可以尝试使用一个子进程来处理图像帧并输出结果,而主进程负责监听子进程的输出,并在接收到新的帧数据时进行刷新,而不是清除整个输出。

以下是修改后的代码示例:


import cv2
import os
from multiprocessing import Pool, Queue, Process

def process_frame(frame, output_queue):
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    resized_frame = cv2.resize(gray_frame, (160, 48))
    lines = []
    for row in resized_frame:
      line = ''.join(['█' if pixel >= 128 else ' ' for pixel in row])
      lines.append(line)
    output_queue.put(lines)

def print_frames(output_queue, total_frames):
    i = 0
    while i < total_frames:
      lines = output_queue.get()
      for line in lines:
            print(line)
      os.system("cls")
      i += 1
      print("已经打印的帧数:", i)
      print("总帧数:", total_frames)

if __name__ == '__main__':
    video = cv2.VideoCapture('1.mp4')
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))

    pool = Pool()# 创建进程池
    output_queue = Queue()

    print_process = Process(target=print_frames, args=(output_queue, total_frames))
    print_process.start()

    i = 0
    while True:
      ret, frame = video.read()
      if not ret:
            break

      result = pool.apply_async(process_frame, (frame, output_queue))
      i += 1
      print("处理的帧数:", i)

    print_process.join()
    video.release()


这个修改后的代码使用了一个输出队列 output_queue,子进程 process_frame 将处理后的帧数据放入队列中,主进程 print_frames 监听该队列并进行输出。这样,在处理和输出的过程中,不会出现清除整个输出的情况,从而减少眼睛的疲劳感。

如果你还有其他问题,请随时提问。

球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}

陶远航 发表于 2023-9-10 19:19:46

这个问题是由于在每一帧打印后调用os.system("cls")清除屏幕导致的,这会使屏幕闪烁并产生晃动感。为了解决这个问题,可以考虑使用特定的控制台输出库,例如colorama,使用其中的函数来清除屏幕。

首先,安装 colorama 库:
pip install colorama


然后,利用该库改进你的代码如下所示:
import cv2
import os
from multiprocessing import Pool
from colorama import init, AnsiToWin32

# 初始化 colorama 库
init(wrap=False)
stream = AnsiToWin32()
pool = Pool()

def process_frame(frame):
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    resized_frame = cv2.resize(gray_frame, (160, 48))
    lines = []
    for row in resized_frame:
      line = ''.join(['█' if pixel >= 128 else ' ' for pixel in row])
      lines.append(line)
    return lines

if __name__ == '__main__':
    video = cv2.VideoCapture('1.mp4')
    total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
   
    i = 0
    while True:
      ret, frame = video.read()
      if not ret:
            break
      
      result = pool.apply_async(process_frame, (frame,))
      lines = result.get()

      # 清除屏幕
      os.system('cls' if os.name == 'nt' else 'clear')

      for line in lines:
            print(line, file=stream)# 将输出通过 colorama 进行处理,避免屏幕闪烁

      i += 1
      print("已经打印的帧数:", i)
      print("总帧数:", total_frames)
   
    video.release()


这样修改后,使用 colorama 库可以实现在控制台中输出,并避免因清除屏幕造成的闪动问题。
如果问题已经解决,请设置最佳答案

liuhongrun2022 发表于 2023-9-10 19:21:15

Mike_python小 发表于 2023-9-10 19:19
这段代码每打印一帧就会清除,导致在使用多进程时非常晃动,久而久之容易对眼睛造成伤害。为了解决这个问题 ...

眼睛是不晃了,可就是打印不出来

liuhongrun2022 发表于 2023-9-10 19:22:21

陶远航 发表于 2023-9-10 19:19
这个问题是由于在每一帧打印后调用os.system("cls")清除屏幕导致的,这会使屏幕闪烁并产生晃动感。为了解决 ...

眼睛是不晃了,可就是报错

liuhongrun2022 发表于 2023-9-10 19:23:08

isdkz 发表于 2023-9-10 19:19
这段代码每打印一帧就会清除,可以通过在控制台上打印 ANSI 转义序列来实现在同一位置上更新帧。以下是修改 ...

还是gpt4聪明{:10_256:}

歌者文明清理员 发表于 2023-9-10 19:46:08

liuhongrun2022 发表于 2023-9-10 19:23
还是gpt4聪明

liuhongrun2022 发表于 2023-9-10 19:53:12

歌者文明清理员 发表于 2023-9-10 19:46


《3.gif官方版下载》
页: [1]
查看完整版本: print问题