我目前正在做一些研究,以检测和定位一个文本光标(你知道,闪烁的矩形形状,当你在你的电脑上键入字符位置)从屏幕记录视频。为此,我使用自定义对象数据集对YOLOv4模型进行了培训(我从这里获得了一个参考),并计划实现跟踪移动光标的DeepSORT。
下面是用于培训YOLOv4的培训数据示例:


以下是我想要达到的目标:

您认为使用YOLOv4 + DeepSORT对此任务是否过分呢?我问这个问题是因为到目前为止,只有70%-80%的包含文本光标的视频帧可以被模型成功地检测到。如果它毕竟是过火的,那么您知道可以为这个任务实现的其他方法吗?
无论如何,我计划不仅从Visual代码窗口检测文本光标,还从浏览器(例如Google )和文本处理器(例如Microsoft )检测文本光标。就像这样:


我认为滑动窗口方法是一种替代方法,但据我所读,该方法可能消耗大量资源,执行速度更慢。我也在考虑来自OpenCV (像这样)的模板匹配,但我不认为它会比YOLOv4执行得更好和更快。
约束是关于性能速度(即在给定的时间内可以处理多少帧)和检测精度(即,我希望避免作为文本光标检测到的字母'l‘或'1’,因为这些字符在某些字体中是相似的)。但较高的精度,较慢的FPS是可以接受的,我认为。
我目前正在使用Python、Tensorflow和OpenCV。非常感谢!
发布于 2021-04-04 17:31:15
如果光标是屏幕上唯一的移动对象,这将有效。以下是之前和之后的内容:
在此之前:

之后:

守则:
import cv2
import numpy as np
BOX_WIDTH = 10
BOX_HEIGHT = 20
def process_img(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
kernel = np.ones((5, 5))
img_canny = cv2.Canny(img_gray, 50, 50)
return img_canny
def get_contour(img):
contours, hierarchies = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
if contours:
return max(contours, key=cv2.contourArea)
def get_line_tip(cnt1, cnt2):
x1, y1, w1, h1 = cv2.boundingRect(cnt1)
if h1 > BOX_HEIGHT / 2:
if np.any(cnt2):
x2, y2, w2, h2 = cv2.boundingRect(cnt2)
if x1 < x2:
return x1, y1
return x1 + w1, y1
def get_rect(x, y):
half_width = BOX_WIDTH // 2
lift_height = BOX_HEIGHT // 6
return (x - half_width, y - lift_height), (x + half_width, y + BOX_HEIGHT - lift_height)
cap = cv2.VideoCapture("screen_record.mkv")
success, img_past = cap.read()
cnt_past = np.array([])
line_tip_past = 0, 0
while True:
success, img_live = cap.read()
if not success:
break
img_live_processed = process_img(img_live)
img_past_processed = process_img(img_past)
img_diff = cv2.bitwise_xor(img_live_processed, img_past_processed)
cnt = get_contour(img_diff)
line_tip = get_line_tip(cnt, cnt_past)
if line_tip:
cnt_past = cnt
line_tip_past = line_tip
else:
line_tip = line_tip_past
rect = get_rect(*line_tip)
img_past = img_live.copy()
cv2.rectangle(img_live, *rect, (0, 0, 255), 2)
cv2.imshow("Cursor", img_live)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()把它拆开:
import cv2
import numpy as npBOX_WIDTH = 10
BOX_HEIGHT = 20def process_img(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
kernel = np.ones((5, 5))
img_canny = cv2.Canny(img_gray, 50, 50)
return img_cannydef get_contour(img):
contours, hierarchies = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
if contours:
return max(contours, key=cv2.contourArea)def get_line_tip(cnt1, cnt2):
x1, y1, w1, h1 = cv2.boundingRect(cnt1)
if h1 > BOX_HEIGHT / 2:
if np.any(cnt2):
x2, y2, w2, h2 = cv2.boundingRect(cnt2)
if x1 < x2:
return x1, y1
return x1 + w1, y1BOX_WIDTH和BOX_HEIGHT常量返回一个框:def get_rect(x, y):
half_width = BOX_WIDTH // 2
lift_height = BOX_HEIGHT // 6
return (x - half_width, y - lift_height), (x + half_width, y + BOX_HEIGHT - lift_height)cap = cv2.VideoCapture("screen_record.mkv")
success, img_past = cap.read()
cnt_past = np.array([])
line_tip_past = 0, 0while循环,并从视频中读取。在视频中处理该帧和该帧之前的帧:while True:
success, img_live = cap.read()
if not success:
break
img_live_processed = process_img(img_live)
img_past_processed = process_img(img_past)cv2.bitwise_xor方法来找出帧之间的差异,以获得屏幕上的移动位置。然后,我们可以使用定义的get_contour函数找到两个帧之间的运动轮廓: img_diff = cv2.bitwise_xor(img_live_processed, img_past_processed)
cnt = get_contour(img_diff)get_line_tip函数来找到光标的尖端。如果找到了提示,将其保存到line_tip_past变量中,以便用于下一次迭代,如果没有找到提示,则可以将以前保存的提示作为当前提示保存: line_tip = get_line_tip(cnt, cnt_past)
if line_tip:
cnt_past = cnt
line_tip_past = line_tip
else:
line_tip = line_tip_pastget_rect函数定义一个矩形,并将其绘制到当前框架上。但在绘制它之前,我们将框架保存为下一次迭代的当前框架之前的框架: rect = get_rect(*line_tip)
img_past = img_live.copy()
cv2.rectangle(img_live, *rect, (0, 0, 255), 2) cv2.imshow("Cursor", img_live)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()https://stackoverflow.com/questions/66929833
复制相似问题