qml Camera VideoOutput QZXingFilter 低帧率识别视频中的二维码 代码
时间: 2023-07-31 09:12:46 浏览: 79
QZXing 实现二维码解码
以下是使用OpenGL进行图像处理的QZXingFilter代码实现:
```qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtMultimedia 5.15
import QtQml 2.15
import QZXing 2.3
ShaderEffect {
property bool useOpenGL: true
property int maxThreads: 1024
readonly property int workerCount: Math.min(QtConcurrent.threadCount, maxThreads)
readonly property int threadBlockSize: Math.ceil(pixelSize.width / workerCount)
readonly property int threadBlockCount: Math.ceil(pixelSize.height)
property bool flipHorizontally: false
property bool flipVertically: false
property bool detectMirrored: false
property real threshold: 0.6
property bool invert: false
readonly property bool hasResult: bool
readonly property string result: _result
signal resultChanged
source: ShaderEffectSource {
id: source
hideSource: true
}
property int width: source.sourceSize.width
property int height: source.sourceSize.height
property real pixelRatio: 1.0
readonly property real2x pixelSize: real2x(width) * real2x(pixelRatio ? pixelRatio : 1.0) x real2x(height) * real2x(pixelRatio ? pixelRatio : 1.0)
uniform highp vec2 pixelSize: vec2(1.0, 1.0)
uniform highp bool flipHorizontally: false
uniform highp bool flipVertically: false
const lowp vec3 W = vec3(0.2125, 0.7154, 0.0721);
varying highp vec2 textureCoord;
uniform sampler2D source;
uniform highp int detectMirrored: 0;
uniform highp float threshold: 0.6;
uniform highp bool invert: false;
uniform highp float sigma: 1.0;
uniform highp int kernelSize: 3;
uniform highp float kernel[9];
uniform highp bool useOpenGL: true;
const highp vec2 dx = vec2(1.0 / pixelSize.x, 0.0);
const highp vec2 dy = vec2(0.0, 1.0 / pixelSize.y);
void main()
{
highp vec4 color = texture2D(source, textureCoord);
if(flipHorizontally)
color.rgba = color.bgra;
if(flipVertically)
color.rgba = color.abgr;
if(detectMirrored > 0)
{
highp vec4 mirroredColor = texture2D(source, vec2(1.0 - textureCoord.x, textureCoord.y));
if(flipHorizontally)
mirroredColor.rgba = mirroredColor.bgra;
if(flipVertically)
mirroredColor.rgba = mirroredColor.abgr;
color.r += mirroredColor.r;
color.g += mirroredColor.g;
color.b += mirroredColor.b;
color.a += mirroredColor.a;
color.rgba /= 2.0;
}
highp float gray = dot(color.rgb, W);
if(invert)
gray = 1.0 - gray;
highp vec4 newColor = vec4(vec3(gray), color.a);
if(useOpenGL)
{
if(textureCoord.x < kernelSize / 2.0 / pixelSize.x || textureCoord.y < kernelSize / 2.0 / pixelSize.y ||
textureCoord.x > 1.0 - kernelSize / 2.0 / pixelSize.x || textureCoord.y > 1.0 - kernelSize / 2.0 / pixelSize.y)
{
gl_FragColor = newColor;
return;
}
highp float sum = 0.0;
for(int i = -kernelSize / 2; i <= kernelSize / 2; i++)
{
for(int j = -kernelSize / 2; j <= kernelSize / 2; j++)
{
highp vec4 neighborColor = texture2D(source, textureCoord + vec2(i, j) * pixelSize);
if(flipHorizontally)
neighborColor.rgba = neighborColor.bgra;
if(flipVertically)
neighborColor.rgba = neighborColor.abgr;
highp float neighborGray = dot(neighborColor.rgb, W);
if(invert)
neighborGray = 1.0 - neighborGray;
sum += neighborGray * kernel[(i + kernelSize / 2) + (j + kernelSize / 2) * kernelSize];
}
}
highp float avg = sum / (kernelSize * kernelSize);
highp float thresholdValue = detectMirrored > 0 ? 0.5 : threshold;
highp float result = avg < thresholdValue ? 0.0 : 1.0;
_result = "";
if(result > 0.0)
{
QZXing decoder;
_result = decoder.decodeImage(source.image, width, height, QZXing::DecoderFormat_QR_CODE);
if(!_result.isEmpty())
resultChanged();
}
gl_FragColor = newColor;
}
else
{
gl_FragColor = newColor;
if(mod(gl_FragCoord.y, float(threadBlockCount)) == 0.0 && mod(gl_FragCoord.x, float(threadBlockSize)) == 0.0)
{
highp int x = int(gl_FragCoord.x / float(threadBlockSize));
highp int y = int(gl_FragCoord.y / float(threadBlockCount));
if(x == 0 || y == 0 || x >= workerCount || y >= threadBlockCount)
return;
highp float sum = 0.0;
for(int i = -kernelSize / 2; i <= kernelSize / 2; i++)
{
for(int j = -kernelSize / 2; j <= kernelSize / 2; j++)
{
highp vec4 neighborColor = texture2D(source, textureCoord + vec2(i, j) * pixelSize);
if(flipHorizontally)
neighborColor.rgba = neighborColor.bgra;
if(flipVertically)
neighborColor.rgba = neighborColor.abgr;
highp float neighborGray = dot(neighborColor.rgb, W);
if(invert)
neighborGray = 1.0 - neighborGray;
sum += neighborGray * kernel[(i + kernelSize / 2) + (j + kernelSize / 2) * kernelSize];
}
}
highp float avg = sum / (kernelSize * kernelSize);
highp float thresholdValue = detectMirrored > 0 ? 0.5 : threshold;
highp float result = avg < thresholdValue ? 0.0 : 1.0;
_result = "";
if(result > 0.0)
{
QZXing decoder;
_result = decoder.decodeImage(source.image, width, height, QZXing::DecoderFormat_QR_CODE);
if(!_result.isEmpty())
resultChanged();
}
}
}
}
}
```
使用OpenGL进行图像处理的QZXingFilter使用方式与原来的QZXingFilter相同,只需将useOpenGL属性设置为true即可。同时,为了提高识别准确率,还可以将VideoOutput的framesPerSecond属性设置为更高的值,例如30。
阅读全文