繁体   English   中英

使用 opencv videowriter python 提高视频中的图像质量

[英]improve image quality in video with opencv videowriter python

我正在尝试从从二进制日志文件中读取的图像创建视频。 然而,output 视频较低,但 output 文件属性在文件大小和图像大小、fps 和持续时间的相同设置下看起来不错。 这是我的代码。

目前调整大小之前的img大小是

我希望我没有对图像大小设置做任何错误。

我使用以下命令创建了文件:

data.astype('int16').tofile(r"data1.out")

获得data后,我将执行以下步骤来获取img ,因为data表示为每像素 12 位。

看起来您解压缩 12 位的方式不正确。

  • fst_uint8的低 4 位是mid_uint8的高 4 位( fst_uint12是低 8 位)。
    mid_uint8 ******** fst_uint8 ********
    fst_uint12 |||| ||||||||
    解包fst_uint12的代码:

     fst_uint12 = fst_uint8 + ((mid_uint8 & 0xF) << 8)
  • lst_uint8的高 4 位是mid_uint8的低 4 位(而snd_uint12是高 8 位)。
    lst_uint8 ******** mid_uint8 ********
    snd_uint12 |||||||| ||||
    解压snd_uint12的代码:

     snd_uint12 = (lst_uint8 << 4) + (mid_uint8 >> 4)

构建 12 位图像后,结果类似于CFA (滤色器阵列)图像。
CFA 不是经典的拜耳过滤器,而是我无法识别的其他东西。
注意:可能是我的解释是错误的,它根本不是滤色器阵列。


这是一个读取'data1.out'的代码,解压 12 位,然后转换为 BGR:

import numpy as np
import cv2

width, height = 1824, 992  # Image width and height.

data = np.fromfile('data1.out', np.uint16)  # Read data from file into 1D NumPy array as type uin16
data = data.astype(np.uint8)  # np.max(data) is 255, so I have to assume data is actually uint8 - convert data to uint8.

# Separate data into low, mid and high bytes - before unpacking 12 bits elements.
fst_uint8 = data[0::3].astype(np.uint16)  # Convert to uint16 (used at the next stage).
mid_uint8 = data[1::3].astype(np.uint16)
lst_uint8 = data[2::3].astype(np.uint16)

# Unpack first 12 bits:
# Lower 4 bits of mid_uint8 are the upper 4 bits of fst_uint12 (and fst_uint8 are the lower 8 bits).
# mid_uint8   ********   fst_uint8   ********
# fst_uint12      ||||               ||||||||
fst_uint12 = fst_uint8 + ((mid_uint8 & 0xF) << 8)

# Unpack second 12 bits:
# Upper 4 bits of mid_uint8 are the lower 4 bits of snd_uint12 (and lst_uint8 are the upper 8 bits).
# lst_uint8   ********   mid_uint8   ********
# snd_uint12  ||||||||               ||||
snd_uint12 = (lst_uint8 << 4) + (mid_uint8 >> 4)

# Interleave fst_uint12 and snd_uint12
data_uint12 = np.zeros(len(fst_uint12)*2)
data_uint12[0::2] = fst_uint12
data_uint12[1::2] = snd_uint12

# Reshape data_uint12 into img
img = np.reshape(data_uint12, (height, width))

# Convert to uint8 - simply divide by 16 (loose some accuracy, but its good enough for getting a sample).
img = (img//16).astype(np.uint8)

# Apply demosaic - not sure it is correct.
bgr_img = cv2.cvtColor(img, cv2.COLOR_BAYER_GB2BGR)

bgr_img = cv2.resize(bgr_img, (912, 496)) # Resize bgr_img

# Show images for testing
cv2.imshow('img', img)
cv2.imshow('bgr_img', bgr_img)
cv2.waitKey()
cv2.destroyAllWindows()

结果:

bgr_img
由于 OP 请求,图像已被删除。

img
由于 OP 请求,图像已被删除。


应用对比度增强:

线性对比度增强示例(请参阅: 使用百分比增强对比度)。

# Reshape data_uint12 into img
img = np.reshape(data_uint12, (height, width))

# Crop relevant ROI
img = img[40:978, 100:1714]

# Apply linear "stretch" - lo goes to 0, and hi goes to 1
lo, hi = np.percentile(img, (1, 99))  # 1% - Low percentile, 99% - High percentile
stretch_img = (img.astype(float) - lo) / (hi-lo)
stretch_img = np.maximum(np.minimum(stretch_img*255, 255), 0).astype(np.uint8)  # Multiply by 255, clamp range to [0, 255] and convert to uint8

# Apply demosaic - not sure it is correct.
stretch_bgr = cv2.cvtColor(stretch_img, cv2.COLOR_BAYER_GB2BGR)
stretch_bgr = cv2.resize(stretch_bgr, (912, 496)) # Resize bgr_img

CLAHE示例(应用灰度图像的示例):

# Create a CLAHE object (Arguments are optional).
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(cv2.cvtColor(stretch_bgr, cv2.COLOR_BGR2GRAY))  # Convert BGR to gray-scale and apply contrast enhancement.

结果:

stretch_bgr
由于 OP 请求,图像已被删除。

cl1
由于 OP 请求,图像已被删除。


更新:

处理RCCC彩色滤光片阵列:

正如 Dan Mašek 评论的那样,原始图像格式应用RCCC Color Filter Array

在此处输入图像描述

具体排序为:
CR
CC
(红色通道位于每 2x2 像素的右上角)。

我们可以根据以下论文重构“清晰通道”(亮度): Engineer-to-Engineer Note :

# Reshape data_uint12 into img
img = np.reshape(data_uint12, (height, width))


# The CFA is RCCC
# Color Filter Array ordering:
# CR
# CC

img = np.reshape(data_uint12, (height, width)).astype(np.uint16)

img = img[40:978, 100:1714]  # Crop relevant ROI

# Reconstruct C (clear pixel value), in position of red pixels.
# Apply convolution as described here:
# https://www.analog.com/media/en/technical-documentation/application-notes/EE358.pdf

k = np.array([[ 0,  0, -1,  0,  0],
              [ 0,  0,  2,  0,  0],
              [-1,  2,  4,  2, -1],
              [ 0,  0,  2,  0,  0],
              [ 0,  0, -1,  0,  0]], float) * (1.0/8.0)

tmp_img = cv2.filter2D(img, -1, k)  # Convolve image with kernel k
tmp_img = np.minimum(tmp_img, 4095)  # Limit result to valid range of 12 bits.

# Image of "clear" pixels - replace original "red" pixels with values of red pixels after filter2D.
c_img = img.copy()
c_img[0::2, 1::2] = tmp_img[0::2, 1::2]

cv2.imshow('c_img', c_img*16)  # Show image for testing
cv2.waitKey()

cv2.imwrite('c_img.png', cv2.resize((c_img//16).astype(np.uint8), (912, 496)))

修复 colors:
由于只有清晰像素和红色像素,我们无法重建绿色和蓝色 colors。
下面的代码构建了一个“假色”红色图像。
“带红色的图像”不是对红色的精确重建,它只是类似于图像应该看起来的样子(假设只有红色和清晰的通道)。

为了构建图像,我使用了以下阶段:

  • 通过调整大小提取红色通道 - 假设它足够好。
  • 从透明和红色通道计算绿色和蓝色通道(假设绿色和蓝色相等)。
  • 从 BGR 转换为 YCrCb 颜色格式。
  • 在 Cb 通道中放置 128 的值(消除蓝色)。
  • 在 Y 通道上应用 CLAHE 对比度增强。
  • 从 YCrCb 转换回 BGR。

这是代码:

# Extract red color channel by resizing - assume it's good enough.
r_img = cv2.resize(img[0::2, 1::2], (img.shape[1], img.shape[0]))


# In YUV color space: Y = 0.2126*R + 0.7152*G + 0.0722*B
# We know Y (Y applies clear channel) and R, but we don't know G and B.
# For simplicity, assume G = B.
# Y = 0.2126*R + (0.7152+0.0722)*G ==> G = (Y - 0.2126*R)/(0.7152+0.0722) and B = G
g_img = c_img - 0.2126*r_img / (0.7152+0.0722)
b_img = g_img
tmp_bgr_img = (np.dstack((b_img, g_img, r_img))//16).astype(np.uint8)  # Merge channels and convert to uint8

# Convert BGR to YCrCb
ycrcb_img = cv2.cvtColor(tmp_bgr_img, cv2.COLOR_BGR2YCrCb)

# Cr approximates red color hue
# Cb approximates blue color hue
# Place 128 in Cb, because there is no blue color (keep only Cr)
ycrcb_img[:, :, 2] = 128

# Apply CLAHE enhancement on Y channel - remark: the conventional way is converting BGR to LAB and apply CLAHE on L.
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
ycrcb_img[:, :, 0] = clahe.apply(ycrcb_img[:, :, 0])
    
# Convert back to BGR - build image with gray and red colors:
reddish_bgr_img = cv2.cvtColor(ycrcb_img, cv2.COLOR_YCrCb2BGR)

cv2.imshow('reddish_bgr_img', reddish_bgr_img)  # Show image for testing
cv2.waitKey()

cv2.imwrite('reddish_bgr_img.png', cv2.resize(reddish_bgr_img, (912, 496)))

结果:
由于 OP 请求,图像已被删除。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM