检测噪声帧
Detecting noise frames
我有一个 FPV(第一人称视角)接收器,它显示从安装在无人机上的 FPV 相机接收的帧。当发射器工作时,接收器显示相机视图。否则,如果连接丢失或发射器不工作,它会显示噪声帧。
噪声帧具有随机模式(有时白色像素较多,有时黑色像素较多)。我想在 Python 中使用 OpenCV 以有效的方式检测那些噪声帧。我知道 OpenCV 有一个方法叫做 cv2.fastNlMeansDenoisingColored()
。但在这种情况下,我想检测每帧中的噪声帧而不是噪声。
附上噪声帧样本:
另一个噪声帧示例:
一个有效的框架(可以是任何东西):
假设您的有效视频帧至少具有一定数量的颜色信息,并且您的噪声帧或多或少是黑白的,可能有一种简单的方法使用 HSV color space.
- 使用 space 将图像转换为 HSV 颜色,参见
cv2.cvtColor
。
- 计算饱和度通道的直方图,见
cv2.calcHist
。
- 计算具有最小饱和度的像素百分比,比方说至少
0.05
。
- 如果该百分比超过阈值,比方说
0.5
,则所有像素中至少有百分之五十的饱和度至少为 0.05
,因此该帧似乎是有效帧。 (如果需要,调整阈值。)
import cv2
from matplotlib import pyplot as plt
import numpy as np
from skimage import io # Only needed for web grabbing images, use cv2.imread for local images
def is_valid(image):
# Convert image to HSV color space
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# Calculate histogram of saturation channel
s = cv2.calcHist([image], [1], None, [256], [0, 256])
# Calculate percentage of pixels with saturation >= p
p = 0.05
s_perc = np.sum(s[int(p * 255):-1]) / np.prod(image.shape[0:2])
##### Just for visualization and debug; remove in final
plt.plot(s)
plt.plot([p * 255, p * 255], [0, np.max(s)], 'r')
plt.text(p * 255 + 5, 0.9 * np.max(s), str(s_perc))
plt.show()
##### Just for visualization and debug; remove in final
# Percentage threshold; above: valid image, below: noise
s_thr = 0.5
return s_perc > s_thr
# Read example images; convert to grayscale
noise1 = cv2.cvtColor(io.imread('https://i.stack.imgur.com/Xz9l0.png'), cv2.COLOR_RGB2BGR)
noise2 = cv2.cvtColor(io.imread('https://i.stack.imgur.com/9ZPAj.jpg'), cv2.COLOR_RGB2BGR)
valid = cv2.cvtColor(io.imread('https://i.stack.imgur.com/0FNPQ.jpg'), cv2.COLOR_RGB2BGR)
for img in [noise1, noise2, valid]:
print(is_valid(img))
可视化输出(按照问题中出现的顺序):
并且,主要输出:
False
False
True
删除整个可视化内容,is_valid
调用在我的机器上每张图像需要不到 0.01 秒。不确定,你在录制时使用的是哪种硬件,但也许这种方法也适用于一些具有足够帧速率的 "real-time" 处理。
最后一点:我试图摆脱 OpenCV 直方图,直接使用 NumPy 计算百分比,但这比目前的方法花费了更多时间。奇怪。
希望对您有所帮助!
我有一个 FPV(第一人称视角)接收器,它显示从安装在无人机上的 FPV 相机接收的帧。当发射器工作时,接收器显示相机视图。否则,如果连接丢失或发射器不工作,它会显示噪声帧。
噪声帧具有随机模式(有时白色像素较多,有时黑色像素较多)。我想在 Python 中使用 OpenCV 以有效的方式检测那些噪声帧。我知道 OpenCV 有一个方法叫做 cv2.fastNlMeansDenoisingColored()
。但在这种情况下,我想检测每帧中的噪声帧而不是噪声。
附上噪声帧样本:
另一个噪声帧示例:
一个有效的框架(可以是任何东西):
假设您的有效视频帧至少具有一定数量的颜色信息,并且您的噪声帧或多或少是黑白的,可能有一种简单的方法使用 HSV color space.
- 使用 space 将图像转换为 HSV 颜色,参见
cv2.cvtColor
。 - 计算饱和度通道的直方图,见
cv2.calcHist
。 - 计算具有最小饱和度的像素百分比,比方说至少
0.05
。 - 如果该百分比超过阈值,比方说
0.5
,则所有像素中至少有百分之五十的饱和度至少为0.05
,因此该帧似乎是有效帧。 (如果需要,调整阈值。)
import cv2
from matplotlib import pyplot as plt
import numpy as np
from skimage import io # Only needed for web grabbing images, use cv2.imread for local images
def is_valid(image):
# Convert image to HSV color space
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# Calculate histogram of saturation channel
s = cv2.calcHist([image], [1], None, [256], [0, 256])
# Calculate percentage of pixels with saturation >= p
p = 0.05
s_perc = np.sum(s[int(p * 255):-1]) / np.prod(image.shape[0:2])
##### Just for visualization and debug; remove in final
plt.plot(s)
plt.plot([p * 255, p * 255], [0, np.max(s)], 'r')
plt.text(p * 255 + 5, 0.9 * np.max(s), str(s_perc))
plt.show()
##### Just for visualization and debug; remove in final
# Percentage threshold; above: valid image, below: noise
s_thr = 0.5
return s_perc > s_thr
# Read example images; convert to grayscale
noise1 = cv2.cvtColor(io.imread('https://i.stack.imgur.com/Xz9l0.png'), cv2.COLOR_RGB2BGR)
noise2 = cv2.cvtColor(io.imread('https://i.stack.imgur.com/9ZPAj.jpg'), cv2.COLOR_RGB2BGR)
valid = cv2.cvtColor(io.imread('https://i.stack.imgur.com/0FNPQ.jpg'), cv2.COLOR_RGB2BGR)
for img in [noise1, noise2, valid]:
print(is_valid(img))
可视化输出(按照问题中出现的顺序):
并且,主要输出:
False
False
True
删除整个可视化内容,is_valid
调用在我的机器上每张图像需要不到 0.01 秒。不确定,你在录制时使用的是哪种硬件,但也许这种方法也适用于一些具有足够帧速率的 "real-time" 处理。
最后一点:我试图摆脱 OpenCV 直方图,直接使用 NumPy 计算百分比,但这比目前的方法花费了更多时间。奇怪。
希望对您有所帮助!