鱼C论坛

 找回密码
 立即注册
查看: 2725|回复: 8

[已解决]print问题

[复制链接]
发表于 2023-9-10 19:19:18 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

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

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

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

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

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

  29.     video.release()
复制代码
最佳答案
2023-9-10 19:19:28
这段代码每打印一帧就会清除,可以通过在控制台上打印 ANSI 转义序列来实现在同一位置上更新帧。以下是修改后的代码:

  1. import cv2
  2. import os
  3. from multiprocessing import Pool

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

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

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

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

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

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

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

  33.     video.release()
复制代码


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

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-9-10 19:19:28 | 显示全部楼层    本楼为最佳答案   
这段代码每打印一帧就会清除,可以通过在控制台上打印 ANSI 转义序列来实现在同一位置上更新帧。以下是修改后的代码:

  1. import cv2
  2. import os
  3. from multiprocessing import Pool

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

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

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

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

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

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

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

  33.     video.release()
复制代码


在这个修改后的代码中,我们使用 ANSI 转义序列来实现在同一位置上更新帧。 ERASE_LINE  变量用于清除当前行, CURSOR_UP_ONE  变量用于将光标移动到上一行,以便在同一位置上更新帧。 print(CURSOR_UP_ONE * len(lines), end='')  用于将光标移动到帧的第一行,以便下一帧能够在正确的位置上打印。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

以下是修改后的代码示例:
  1. import cv2
  2. import os
  3. from multiprocessing import Pool, Queue, Process
  4. def process_frame(frame, output_queue):
  5.     gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  6.     resized_frame = cv2.resize(gray_frame, (160, 48))
  7.     lines = []
  8.     for row in resized_frame:
  9.         line = ''.join(['█' if pixel >= 128 else ' ' for pixel in row])
  10.         lines.append(line)
  11.     output_queue.put(lines)
  12. def print_frames(output_queue, total_frames):
  13.     i = 0
  14.     while i < total_frames:
  15.         lines = output_queue.get()
  16.         for line in lines:
  17.             print(line)
  18.         os.system("cls")
  19.         i += 1
  20.         print("已经打印的帧数:", i)
  21.         print("总帧数:", total_frames)
  22. if __name__ == '__main__':
  23.     video = cv2.VideoCapture('1.mp4')
  24.     total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
  25.     pool = Pool()  # 创建进程池
  26.     output_queue = Queue()
  27.     print_process = Process(target=print_frames, args=(output_queue, total_frames))
  28.     print_process.start()
  29.     i = 0
  30.     while True:
  31.         ret, frame = video.read()
  32.         if not ret:
  33.             break
  34.         result = pool.apply_async(process_frame, (frame, output_queue))
  35.         i += 1
  36.         print("处理的帧数:", i)
  37.     print_process.join()
  38.     video.release()
复制代码

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

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

球一个最佳答案谢谢啦!这对我非常重要!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

首先,安装 colorama 库:
  1. pip install colorama
复制代码


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

  5. # 初始化 colorama 库
  6. init(wrap=False)
  7. stream = AnsiToWin32()
  8. pool = Pool()

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

  17. if __name__ == '__main__':
  18.     video = cv2.VideoCapture('1.mp4')
  19.     total_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
  20.    
  21.     i = 0
  22.     while True:
  23.         ret, frame = video.read()
  24.         if not ret:
  25.             break
  26.         
  27.         result = pool.apply_async(process_frame, (frame,))
  28.         lines = result.get()

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

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

  33.         i += 1
  34.         print("已经打印的帧数:", i)
  35.         print("总帧数:", total_frames)
  36.    
  37.     video.release()
复制代码


这样修改后,使用 colorama 库可以实现在控制台中输出,并避免因清除屏幕造成的闪动问题。
如果问题已经解决,请设置最佳答案
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

眼睛是不晃了,可就是打印不出来
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

眼睛是不晃了,可就是报错
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

还是gpt4聪明
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-10 19:46:08 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-9-10 19:53:12 | 显示全部楼层
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-22 17:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表