Calarence 2017-12-18 02:26 采纳率: 0%
浏览 3234
已采纳

Win7采集摄像头数据显示图像回抖

开发环境:VS2015+qt5.7+相机驱动

实现方案:通过驱动配置回调函数,获取相机数据,然后把数据放入到数据缓冲区;
然后开启一个线程读取缓冲队列的数据,拷贝到一帧图像的缓冲块,并使用opengl(QOpenglWidget)
进行显示(updata()-onFrameSwapped()中emit render消息,次线程SLot进行显示)。
显示代码如下:
void GLThreadWidget::UpdateShowImage()
{
update();
}

void GLThreadWidget::onFrameSwapped()
{
m_renderer->unlockRenderer();

if (IsShowUpdateflag() == true)
{
    emit renderRequested();//f发送消息
}

}
//槽函数
void Renderer::render()
{
if (m_exiting)
return;

bool needrender = m_glwidget->IsShowUpdateflag();
if (needrender == false)
    return;




QImage * pimage = m_glwidget->GetCurImage();

if (pimage == nullptr)
    return;


QOpenGLContext *ctx = m_glwidget->context();

if (!ctx) // QOpenGLWidget not yet initialized
{

    m_glwidget->SetShowUpdateFlagFalse();
    return;
}
if (ctx->thread() == QThread::currentThread())
{
    //qDebug() << "ctx->thread()" << ctx->thread();
    m_glwidget->SetShowUpdateFlagFalse();
    return;
}

// Grab the context.
m_grabMutex.lock();
emit contextWanted();
m_grabCond.wait(&m_grabMutex);
QMutexLocker lock(&m_renderMutex);
m_grabMutex.unlock();

if (m_exiting)
    return;

Q_ASSERT(ctx->thread() == QThread::currentThread());

// Make the context (and an offscreen surface) current for this thread. The
// QOpenGLWidget's fbo is bound in the context.
m_glwidget->makeCurrent();

if (!m_inited)
{
    m_inited = true;
    initializeOpenGLFunctions();

    initShaders();
    initTextures();
    initBuffArray();



}
//initializeOpenGLFunctions();
GLfloat *pViewRect = m_glwidget->GetViewPortForRender();
glViewport(pViewRect[0], pViewRect[1], pViewRect[2], pViewRect[3]);


glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);


// pimage = m_glwidget->GetCurImage();
int width;
int height;
m_glwidget->GetImageSize(width, height);
m_texture->destroy();
m_texture->create();

m_texture->setSize(width, height);
m_texture->setData((*pimage).mirrored());
m_program->bind();
m_texture->bind();



QMatrix4x4 m;


this->m_program->setUniformValue(m_projviewUniform, m);
this->m_program->setUniformValue(m_textureUniform, 0);
// Draw cube geometry using indices from VBO 1
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

m_texture->release();
m_program->release();

glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);

// Make no context current on this thread and move the QOpenGLWidget's
// context back to the gui thread.
m_glwidget->doneCurrent();
ctx->moveToThread(qGuiApp->thread());


// Schedule composition. Note that this will use QueuedConnection, meaning
// that update() will be invoked on the gui thread.
QMetaObject::invokeMethod(m_glwidget, "update", Qt::QueuedConnection);

m_glwidget->SetShowUpdateFlagFalse();

// qDebug() << "render finished";

}
方案结果:刚开始能够正常显示,当手在移动的时候,图像也能实时的进行移动。但是
过一段时间之后,图像出现回抖现象。
比如说,手在移动的时候,能看出来显示后面的一帧图像时,又显示了前一帧图像,
看到就是手往回移了一点然后又立马往前移动。

针对此问题怀疑是数据缓冲区对列乱了,但通过使用序号验证,
读取数据用于显示时,显示的序号都是从小到大的,没有出现变小的情况。

异常现象视频:http://v.youku.com/v_show/id_XMzI0MDg5NjYyNA==.html?spm=a2h3j.8428770.3416059.1

正常现象视频:http://v.youku.com/v_show/id_XMzI0MDg5Mzg3Ng==.html?spm=a2h3j.8428770.3416059.1

  • 写回答

2条回答

  • csulizhang 2017-12-18 08:22
    关注

    没有看到你的入队和出队操作是否正确,还有就是你在响应contextWanted事件的时候,资源是否做到了锁定,你只是响应事件的时候加线程锁应该不能够实现处理事件过程中对资源的互斥

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 已采纳回答 9月28日

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?