校园网络建设方案设计,seo基础,石家庄网站建设排名,淘宝官网首页登录注册需求
在视频窗口上进行绘图#xff0c;包括圆#xff0c;矩形#xff0c;扇形等
效果#xff1a; 思路#xff1a;
自己取图然后转成QImage #xff0c;再向QWidget 进行渲染#xff0c;根据以往的经验#xff0c;无法达到很高的帧率。因此决定使用相机SDK自带的渲染…需求
在视频窗口上进行绘图包括圆矩形扇形等
效果 思路
自己取图然后转成QImage 再向QWidget 进行渲染根据以往的经验无法达到很高的帧率。因此决定使用相机SDK自带的渲染功能也就是传一个句柄给到sdk。但是这样视频渲染出来了向上绘制图案会被视频遮挡住因此这里采用了两个窗口叠加然后上层窗口设置透明背景的方式来实现。 底层取图窗口代码
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H#include QWidget
#include windows.h
#include MvCameraControl.h#include ./util/PSEventController.h
#include graphwidget.h
class CameraWidget : public QWidget
{Q_OBJECT
public:explicit CameraWidget(QWidget *parent nullptr);~CameraWidget();void updatePos(int x,int y);private:bool findDevice();bool printDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo);void getImage();bool openDevice();bool closeDevice();private:int nRet MV_OK;void* handle NULL;MV_CC_DEVICE_INFO_LIST stDeviceList {0};std::atomic_bool bExit true;HWND hwnd NULL;GraphWidget * graphWidgetnullptr;QWidget *videoWidget nullptr;std::atomic_bool isCapture{false};private:void initData();void mvToQImage(MV_DISPLAY_FRAME_INFO stDisplayInfo);public slots:void on_psEvent_capture(bool isChecked);void on_psEvent_adjustImage(bool isChecked);void on_psEvent_fixImage(bool isChecked);signals:void capture(QImage image);
};#endif // CAMERAWIDGET_H#include camerawidget.h#include iostream
#include mutex
#include thread
#include QWidget
#include QPainter
#include QGridLayout
#include QStackedLayout
#include QDebug
#include QGraphicsScene
#include QGraphicsView
#include QGraphicsItemCameraWidget::CameraWidget(QWidget *parent): QWidget{parent}
{graphWidget new GraphWidget(this);graphWidget-setWindowFlags(Qt::FramelessWindowHint|Qt::Dialog|Qt::WindowStaysOnTopHint|Qt::SubWindow);graphWidget-setAttribute(Qt::WA_TranslucentBackground, true);QPalette pal;pal.setColor(QPalette::Window,QColor(0,0,0,0));graphWidget-setAutoFillBackground(true);graphWidget-setPalette(pal);graphWidget-show();hwnd (HWND)this-winId();openDevice();this-setFixedSize(816,683);graphWidget-setFixedSize(this-size());setUpdatesEnabled(false);setAttribute(Qt::WA_OpaquePaintEvent);initData();
}CameraWidget::~CameraWidget()
{closeDevice();
}bool CameraWidget::findDevice()
{//枚举设备nRet MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, stDeviceList);if (MV_OK ! nRet){printf(Enum Devices fail! nRet [0x%x]\n, nRet);return false;}if (stDeviceList.nDeviceNum 0){for (unsigned int i 0; i stDeviceList.nDeviceNum; i){printf([device %d]:\n, i);MV_CC_DEVICE_INFO* pDeviceInfo stDeviceList.pDeviceInfo[i];if (NULL pDeviceInfo){break;}printDeviceInfo(pDeviceInfo);}}else{printf(Find No Devices!\n);return false;}return true;
}bool CameraWidget::openDevice()
{if(!findDevice()){return false;}unsigned int nIndex 0;if (nIndex stDeviceList.nDeviceNum){printf(Invalid device index!\n);return false;}do{//选择设备并创建句柄nRet MV_CC_CreateHandle(handle, stDeviceList.pDeviceInfo[nIndex]);if (MV_OK ! nRet){printf(Create Handle fail! nRet [0x%x]\n, nRet);break;}// ch:打开设备nRet MV_CC_OpenDevice(handle);if (MV_OK ! nRet){printf(Open Device fail! nRet [0x%x]\n, nRet);break;}// ch:探测网络最佳包大小(只对GigE相机有效)if (stDeviceList.pDeviceInfo[nIndex]-nTLayerType MV_GIGE_DEVICE){int nPacketSize MV_CC_GetOptimalPacketSize(handle);if (nPacketSize 0){nRet MV_CC_SetIntValue(handle,GevSCPSPacketSize,nPacketSize);if(nRet ! MV_OK){printf(Warning: Set Packet Size fail nRet [0x%x]!, nRet);}}else{printf(Warning: Get Packet Size fail nRet [0x%x]!, nPacketSize);}}//设置触发模式为offnRet MV_CC_SetEnumValue(handle, TriggerMode, 0);if (MV_OK ! nRet){printf(Set Trigger Mode fail! nRet [0x%x]\n, nRet);break;}// ch:开始取流 | en:Start grab imagenRet MV_CC_StartGrabbing(handle);if (MV_OK ! nRet){printf(Start Grabbing fail! nRet [0x%x]\n, nRet);break;}bExitfalse;std::thread t([](){getImage();});t.detach();return true;}while (0);if (nRet ! MV_OK){if (handle ! NULL){MV_CC_DestroyHandle(handle);handle NULL;}}return false;
}bool CameraWidget::closeDevice()
{bExittrue;if (handle NULL)return true;do{// ch:停止取流 | en:Stop grab imagenRet MV_CC_StopGrabbing(handle);if (MV_OK ! nRet){printf(Stop Grabbing fail! nRet [0x%x]\n, nRet);break;}// ch:关闭设备 | Close devicenRet MV_CC_CloseDevice(handle);if (MV_OK ! nRet){printf(ClosDevice fail! nRet [0x%x]\n, nRet);break;}// ch:销毁句柄 | Destroy handlenRet MV_CC_DestroyHandle(handle);if (MV_OK ! nRet){printf(Destroy Handle fail! nRet [0x%x]\n, nRet);break;}handle NULL;return true;}while (0);if (nRet ! MV_OK){if (handle ! NULL){MV_CC_DestroyHandle(handle);handle NULL;}}return false;
}void CameraWidget::initData()
{PSEventController::subscribe(this,capture);PSEventController::subscribe(this,adjustImage);PSEventController::subscribe(this,fixImage);connect(this,CameraWidget::capture,this,[](QImage image){graphWidget-setBackgroundImage(QPixmap::fromImage(image),true);},Qt::UniqueConnection);
}void CameraWidget::on_psEvent_capture(bool isChecked)
{if(!isChecked){QPixmap backgroundImage;graphWidget-setBackgroundImage(backgroundImage,false);}else{isCapturetrue;}
}void CameraWidget::on_psEvent_adjustImage(bool isChecked)
{graphWidget-setIsScale(true);
}void CameraWidget::on_psEvent_fixImage(bool isChecked)
{graphWidget-setIsScale(false);
}void CameraWidget::updatePos(int x, int y)
{graphWidget-move(x,y);
}bool CameraWidget::printDeviceInfo(MV_CC_DEVICE_INFO *pstMVDevInfo)
{if (NULL pstMVDevInfo){printf(The Pointer of pstMVDevInfo is NULL!\n);return false;}if (pstMVDevInfo-nTLayerType MV_GIGE_DEVICE){int nIp1 ((pstMVDevInfo-SpecialInfo.stGigEInfo.nCurrentIp 0xff000000) 24);int nIp2 ((pstMVDevInfo-SpecialInfo.stGigEInfo.nCurrentIp 0x00ff0000) 16);int nIp3 ((pstMVDevInfo-SpecialInfo.stGigEInfo.nCurrentIp 0x0000ff00) 8);int nIp4 (pstMVDevInfo-SpecialInfo.stGigEInfo.nCurrentIp 0x000000ff);// ch:打印当前相机ip和用户自定义名字 | en:print current ip and user defined nameprintf(CurrentIp: %d.%d.%d.%d\n , nIp1, nIp2, nIp3, nIp4);printf(UserDefinedName: %s\n\n , pstMVDevInfo-SpecialInfo.stGigEInfo.chUserDefinedName);}else if (pstMVDevInfo-nTLayerType MV_USB_DEVICE){printf(UserDefinedName: %s\n, pstMVDevInfo-SpecialInfo.stUsb3VInfo.chUserDefinedName);printf(Serial Number: %s\n, pstMVDevInfo-SpecialInfo.stUsb3VInfo.chSerialNumber);printf(Device Number: %d\n\n, pstMVDevInfo-SpecialInfo.stUsb3VInfo.nDeviceNumber);}else{printf(Not support.\n);}return true;
}//std::once_flag flag;
void CameraWidget::getImage()
{int nRet MV_OK;MV_FRAME_OUT stImageInfo {0};MV_DISPLAY_FRAME_INFO stDisplayInfo {0};while(1){nRet MV_CC_GetImageBuffer(handle, stImageInfo, 1000);if (nRet MV_OK){// printf(Get Image Buffer: Width[%d], Height[%d], FrameNum[%d]\n,// stImageInfo.stFrameInfo.nWidth, stImageInfo.stFrameInfo.nHeight, stImageInfo.stFrameInfo.nFrameNum);if (hwnd){stDisplayInfo.hWnd hwnd;stDisplayInfo.pData stImageInfo.pBufAddr;stDisplayInfo.nDataLen stImageInfo.stFrameInfo.nFrameLen;stDisplayInfo.nWidth stImageInfo.stFrameInfo.nWidth;stDisplayInfo.nHeight stImageInfo.stFrameInfo.nHeight;stDisplayInfo.enPixelType stImageInfo.stFrameInfo.enPixelType;//转qt QImage 给到绘图窗口if(isCapture){mvToQImage(stDisplayInfo);}//调整窗口尺寸// std::call_once(flag, [](){// int cW stImageInfo.stFrameInfo.nWidth;// int cH stImageInfo.stFrameInfo.nHeight;// });MV_CC_DisplayOneFrame(handle, stDisplayInfo);}nRet MV_CC_FreeImageBuffer(handle, stImageInfo);if(nRet ! MV_OK){printf(Free Image Buffer fail! nRet [0x%x]\n, nRet);}}else{printf(Get Image fail! nRet [0x%x]\n, nRet);}if(bExit){break;}}
}void CameraWidget::mvToQImage(MV_DISPLAY_FRAME_INFO stDisplayInfo)
{QImage image;if(stDisplayInfo.enPixelTypePixelType_Gvsp_Mono8){image QImage(stDisplayInfo.pData, stDisplayInfo.nWidth, stDisplayInfo.nHeight, QImage::Format_Indexed8);}else if(stDisplayInfo.enPixelTypePixelType_Gvsp_RGB8_Packed){image QImage(stDisplayInfo.pData, stDisplayInfo.nWidth, stDisplayInfo.nHeight, QImage::Format_RGB888);}emit capture(image);isCapturefalse;
}
上层绘图窗口代码
#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H#include QWidget
#include windows.h
#include MvCameraControl.h#include ./util/PSEventController.h
#include graphwidget.h
class CameraWidget : public QWidget
{Q_OBJECT
public:explicit CameraWidget(QWidget *parent nullptr);~CameraWidget();void updatePos(int x,int y);private:bool findDevice();bool printDeviceInfo(MV_CC_DEVICE_INFO* pstMVDevInfo);void getImage();bool openDevice();bool closeDevice();private:int nRet MV_OK;void* handle NULL;MV_CC_DEVICE_INFO_LIST stDeviceList {0};std::atomic_bool bExit true;HWND hwnd NULL;GraphWidget * graphWidgetnullptr;QWidget *videoWidget nullptr;std::atomic_bool isCapture{false};private:void initData();void mvToQImage(MV_DISPLAY_FRAME_INFO stDisplayInfo);public slots:void on_psEvent_capture(bool isChecked);void on_psEvent_adjustImage(bool isChecked);void on_psEvent_fixImage(bool isChecked);signals:void capture(QImage image);
};#endif // CAMERAWIDGET_H#include graphwidget.h
#include QGridLayout
#include QPainter
#include QMouseEvent
#include QDebug#include ../graphics/bqgraphicsitem.h#define VIEW_CENTER viewport()-rect().center()
#define VIEW_WIDTH viewport()-rect().width()
#define VIEW_HEIGHT viewport()-rect().height()GraphWidget::GraphWidget(QWidget *parent): QGraphicsView{parent}
{setAttribute(Qt::WA_TranslucentBackground);setStyleSheet(background: transparent;border:0px);setWindowFlags(Qt::FramelessWindowHint);setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);setRenderHint(QPainter::Antialiasing);scene new QGraphicsScene(this);this-setScene(scene);setDragMode(ScrollHandDrag);this-setSceneRect(this-geometry());centerOn(0, 0);initData();
}void GraphWidget::setIsScale(bool newIsScale)
{isScale newIsScale;if(!isScale){revertSize();}
}void GraphWidget::setBackgroundImage(const QPixmap newBackgroundImage,bool newIsSetBackground)
{qDebug()setBackgroundImage newIsSetBackground;isSetBackgroundnewIsSetBackground;if(backgroundItem){scene-removeItem(backgroundItem);backgroundItemnullptr;}if(isSetBackground){setAttribute(Qt::WA_TranslucentBackground,false);backgroundImage newBackgroundImage;if(!backgroundImage.isNull()){backgroundItem scene-addPixmap(backgroundImage);backgroundItem-setPos(-this-width()/2,-this-height()/2);backgroundItem-setZValue(-1000);backgroundItem-setFlags(QGraphicsItem::ItemIsSelectable |QGraphicsItem::ItemIsMovable |QGraphicsItem::ItemIsFocusable);update();}}else{setAttribute(Qt::WA_TranslucentBackground,true);revertSize();}}void GraphWidget::clearItem()
{for(int i0;iscene-items().size();i){QGraphicsItem *item scene-items().at(i);if(item-zValue()-1000){continue;}else{scene-removeItem(scene-items().at(i));}}
}void GraphWidget::on_psEvent_addLine(bool isChecked)
{clearItem();BRectangle *m_rectangle new BRectangle(0, 0, 100, 50, BGraphicsItem::ItemType::Rectangle);scene-addItem(m_rectangle);
}void GraphWidget::on_psEvent_addCircle(bool isChecked)
{clearItem();BConcentricCircle *m_conCircle new BConcentricCircle(0, 0, 50, 80, BGraphicsItem::ItemType::Concentric_Circle);scene-addItem(m_conCircle);
}void GraphWidget::on_psEvent_addEllipse(bool isChecked)
{clearItem();BEllipse *m_ellipse new BEllipse(0, 0, 100, 50, BGraphicsItem::ItemType::Ellipse);scene-addItem(m_ellipse);
}void GraphWidget::on_psEvent_addArc(bool isChecked)
{clearItem();BPie *m_pie new BPie(0, 0, 80, 30, BGraphicsItem::ItemType::Pie);scene-addItem(m_pie);
}void GraphWidget::wheelEvent(QWheelEvent *event)
{if(isScale){static float scale 1.1;auto angle event-angleDelta();if(angle.y() 0){this-scale(scale, scale);}else{this-scale(1/scale, 1/scale);}}
}void GraphWidget::initData()
{PSEventController::subscribe(this,addLine);PSEventController::subscribe(this,addCircle);PSEventController::subscribe(this,addEllipse);PSEventController::subscribe(this,addArc);
}void GraphWidget::revertSize()
{setTransformationAnchor(QGraphicsView::AnchorViewCenter);QMatrix q;q.setMatrix(1,this-matrix().m12(),this-matrix().m21(),1,this-matrix().dx(),this-matrix().dy());setMatrix(q,false);
}主窗口移动和缩放时更新视频窗口位置
void MainWindow::updateGraphWidgetPos()
{if(cameraWidget){QPoint p mapToGlobal(cameraWidget-parentWidget()-pos());cameraWidget-updatePos(p.x(),p.y()22);}
}void MainWindow::resizeEvent(QResizeEvent *e)
{updateGraphWidgetPos();return QWidget::resizeEvent(e);
}void MainWindow::moveEvent(QMoveEvent *e)
{updateGraphWidgetPos();return QWidget::moveEvent(e);
}