InteractiveFace.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. #include "InteractiveFace.h"
  2. InteractiveFace::InteractiveFace(QObject *parent) : QQuickImageProvider(QQuickImageProvider::Image)
  3. {
  4. initEngine();
  5. if (hasCamera())
  6. {
  7. // initCamera();
  8. }
  9. // 图像取1s 10帧
  10. m_timerId = startTimer(100);
  11. }
  12. bool InteractiveFace::hasCamera()
  13. {
  14. return !QMediaDevices::videoInputs().isEmpty();
  15. }
  16. InteractiveFace::~InteractiveFace()
  17. {
  18. destroyEngine();
  19. }
  20. void InteractiveFace::initEngine()
  21. {
  22. const char* appId = "FTN3G4pk8n2RKwjD955sRapRjbYQFefwhHd4sBZMYEz6";
  23. const char* sdkKey = "BjJomNU2bQc2SYhT7NNqwvFd9zfc72Q7nneh75r3NT3x";
  24. const char* licenseFilePath = "./offlineLicense.dat";
  25. // 超过5次不再尝试获取授权文件
  26. int iLoopCount = 5;
  27. do{
  28. MPChar activeDeviceInfo;
  29. ASFGetActiveDeviceInfo(&activeDeviceInfo);
  30. ASF_ActiveFileInfo activeFileInfo;
  31. MRESULT res = -1;
  32. if ((res = ASFGetActiveFileInfo(&activeFileInfo)) == MOK)
  33. {
  34. qDebug() << "获取版本信息成功";
  35. break;
  36. }
  37. else{
  38. FileLogger::writeToFile("deviceInfo","ArcSoftDeviceInfo.txt",activeDeviceInfo,FileLogger::WriteMode::OVERWRITE);
  39. if(res == 0x1601A){
  40. if((res = ASFOfflineActivation((MPChar)licenseFilePath)) == MOK)
  41. {
  42. qDebug() << "授权成功";
  43. }
  44. }
  45. }
  46. break;
  47. }while(iLoopCount--);
  48. // 初始化引擎
  49. MRESULT res = ASFInitEngine(ASF_DETECT_MODE_VIDEO,
  50. ASF_OP_ALL_OUT,
  51. 1,
  52. ASF_FACE_DETECT | ASF_FACERECOGNITION,
  53. &m_engine);
  54. if (res != MOK)
  55. {
  56. qDebug() << " 初始化引擎失败" << res;
  57. }
  58. }
  59. void InteractiveFace::destroyEngine()
  60. {
  61. }
  62. void InteractiveFace::cameraPlay()
  63. {
  64. // 如果相机不是播放状态
  65. if (!m_camera.isActive())
  66. {
  67. QCameraDevice cameraDevice = QMediaDevices::defaultVideoInput();
  68. if (cameraDevice.isNull())
  69. {
  70. qWarning() << "系统中没有检测到任何摄像机设备";
  71. return;
  72. }
  73. m_camera.setCameraDevice(cameraDevice);
  74. // 确保图像宽度是4的倍数(虹软人脸识别要求)
  75. if (m_camera.cameraFormat().resolution().width() % 4 != 0)
  76. {
  77. QList<QCameraFormat> cameraFormats = cameraDevice.videoFormats();
  78. for (int i = 0; i < cameraFormats.size(); ++i)
  79. {
  80. const QCameraFormat &cameraFormat = cameraFormats.at(i);
  81. if (cameraFormat.resolution().width() % 4 == 0)
  82. {
  83. m_camera.setCameraFormat(cameraFormat);
  84. break;
  85. }
  86. }
  87. }
  88. m_session.setCamera(&m_camera);
  89. m_session.setVideoSink(&m_videoSink);
  90. m_camera.start();
  91. }
  92. }
  93. void InteractiveFace::cameraStop()
  94. {
  95. if (m_camera.isActive())
  96. {
  97. m_camera.stop();
  98. m_camera.setActive(false);
  99. m_camera.setCameraDevice(QCameraDevice());
  100. m_session.setCamera(nullptr);
  101. m_session.setVideoSink(nullptr);
  102. }
  103. }
  104. void InteractiveFace::initCamera()
  105. {
  106. m_camera.setCameraDevice(QMediaDevices::defaultVideoInput());
  107. QCameraDevice device = QMediaDevices::defaultVideoInput();
  108. QList<QCameraFormat> formats = device.videoFormats();
  109. // 选择最适合的格式
  110. for (const QCameraFormat &format : formats)
  111. {
  112. // qDebug() << "fps---" << format.maxFrameRate() << format.resolution().width() << format.resolution().height();
  113. if (format.maxFrameRate() >= 10.0 && format.resolution().width() % 4 == 0)
  114. {
  115. m_camera.setCameraFormat(format);
  116. break;
  117. }
  118. }
  119. m_session.setCamera(&m_camera);
  120. m_session.setVideoSink(&m_videoSink);
  121. }
  122. void InteractiveFace::destroyCamera()
  123. {
  124. }
  125. QString InteractiveFace::getImageUrl()
  126. {
  127. // image://InteractiveFaceImage/(0-9999)
  128. return QString("image://") +
  129. QString(INTERACTIVE_FACE_IMAGE_URL) +
  130. QString("/") +
  131. // 取随机数,确保图片刷新(Qt机制,两次url地址相同,图片不会显示)
  132. QString::number(QRandomGenerator::global()->bounded(10000));
  133. }
  134. // 设置图像采集回调
  135. void InteractiveFace::setCameraImageGatherCallBack(QJSValue callback)
  136. {
  137. m_imageGatherCallback = callback;
  138. }
  139. // 设置发现人脸回调
  140. void InteractiveFace::setCameraImageAppearCallBack(QJSValue callback)
  141. {
  142. m_imageAppearCallback = callback;
  143. }
  144. // 设置人脸停留回调
  145. void InteractiveFace::setCameraImageRemainCallBack(QJSValue callback)
  146. {
  147. m_imageRemainCallback = callback;
  148. }
  149. void InteractiveFace::setCameraImageCallBack(QJSValue gatherCallback,
  150. QJSValue appearCallback,
  151. QJSValue remainCallback)
  152. {
  153. m_imageGatherCallback = gatherCallback;
  154. m_imageAppearCallback = appearCallback;
  155. m_imageRemainCallback = remainCallback;
  156. }
  157. void InteractiveFace::setCallBackFaceStatus(QJSValue isAppearCallback)
  158. {
  159. m_isAppearCallback = isAppearCallback;
  160. }
  161. void InteractiveFace::cameraImagePlay()
  162. {
  163. if (!hasCamera())
  164. {
  165. return;
  166. }
  167. if (!m_camera.isActive())
  168. {
  169. cameraPlay();
  170. m_laseEpoch = 0;
  171. m_laseCount = 0;
  172. m_FrameId = 0;
  173. }
  174. }
  175. void InteractiveFace::cameraImageStop()
  176. {
  177. if (!hasCamera())
  178. {
  179. return;
  180. }
  181. cameraStop();
  182. }
  183. QImage InteractiveFace::requestImage(const QString &, QSize *, const QSize &)
  184. {
  185. return m_image;
  186. }
  187. void InteractiveFace::timerEvent(QTimerEvent *event)
  188. {
  189. if (event->timerId() == m_timerId)
  190. {
  191. if (!hasCamera())
  192. {
  193. return;
  194. }
  195. if (m_camera.isActive())
  196. {
  197. QMutexLocker locker(&m_mutex);
  198. QVideoFrame currentFormat = m_videoSink.videoFrame();
  199. QImage image; // 图像
  200. QPainter painter; // 画笔
  201. // 过滤无效帧, 前10帧不做处理
  202. if(++m_FrameId <= 10)
  203. {
  204. m_image = image.copy();
  205. if (m_imageGatherCallback.isCallable())
  206. {
  207. QJSValueList args;
  208. args << getImageUrl();
  209. m_imageGatherCallback.call(args);
  210. }
  211. return;
  212. }
  213. if (currentFormat.isValid())
  214. {
  215. if (currentFormat.map(QVideoFrame::ReadOnly))
  216. {
  217. image = currentFormat.toImage();
  218. // image = image.scaled(QSize(800, 600), Qt::KeepAspectRatio, Qt::SmoothTransformation);
  219. }
  220. currentFormat.unmap();
  221. }
  222. if (!image.isNull())
  223. {
  224. // image底部框
  225. painter.begin(&image);
  226. painter.setRenderHint(QPainter::Antialiasing);
  227. painter.setFont(QFont("Arial", 24));
  228. painter.setBrush(QColor(255, 255, 255, 127));
  229. painter.setPen(Qt::NoPen);
  230. painter.drawRect(QRect(0, image.height() - 50, image.width(), 50));
  231. QImage convertedImage = image.convertToFormat(QImage::Format_RGB888);
  232. ASVLOFFSCREEN offscreen = {0};
  233. offscreen.u32PixelArrayFormat = ASVL_PAF_RGB24_B8G8R8;
  234. offscreen.i32Width = convertedImage.width();
  235. offscreen.i32Height = convertedImage.height();
  236. offscreen.pi32Pitch[0] = convertedImage.bytesPerLine();
  237. offscreen.ppu8Plane[0] = (MUInt8*)convertedImage.bits();
  238. if (offscreen.ppu8Plane[0])
  239. {
  240. if (m_engine != NULL)
  241. {
  242. ASF_MultiFaceInfo detectedFaces = {0};
  243. MRESULT res = ASFDetectFaces(m_engine,
  244. offscreen.i32Width,
  245. offscreen.i32Height,
  246. offscreen.u32PixelArrayFormat,
  247. offscreen.ppu8Plane[0],
  248. &detectedFaces);
  249. if (res != MOK)
  250. {
  251. qDebug() << "检测人脸失败" << res;
  252. }
  253. bool isAppear;
  254. // 获取第一个人脸
  255. if (res == MOK && detectedFaces.faceNum == 1) {
  256. isAppear = true;
  257. if (m_laseCount <= 0)
  258. {
  259. m_laseCount = 1;
  260. m_laseEpoch = QDateTime::currentSecsSinceEpoch();
  261. }
  262. if (m_imageAppearCallback.isCallable())
  263. {
  264. m_image = image.copy();
  265. QJSValueList args;
  266. args << getImageUrl();
  267. m_imageAppearCallback.call(args);
  268. }
  269. MRECT mrect = detectedFaces.faceRect[0];
  270. qint64 epoch = QDateTime::currentSecsSinceEpoch() - m_laseEpoch;
  271. if (epoch <= 1)
  272. {
  273. painter.setPen(QPen(Qt::blue, 3));
  274. painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
  275. Qt::AlignCenter,
  276. QString("检测到人脸,即将拍摄").arg(epoch));
  277. // 绘制人脸框
  278. painter.setPen(QPen(Qt::green, 2));
  279. painter.setBrush(Qt::NoBrush);
  280. painter.drawRect(QRect(mrect.left,
  281. mrect.top,
  282. mrect.right - mrect.left,
  283. mrect.bottom - mrect.top));
  284. }
  285. else if (epoch > 1 && epoch <= 4)
  286. {
  287. painter.setPen(QPen(Qt::blue, 3));
  288. painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
  289. Qt::AlignCenter,
  290. QString("%1").arg(5 - epoch));
  291. // 绘制人脸框
  292. painter.setPen(QPen(Qt::green, 2));
  293. painter.setBrush(Qt::NoBrush);
  294. painter.drawRect(QRect(mrect.left,
  295. mrect.top,
  296. mrect.right - mrect.left,
  297. mrect.bottom - mrect.top));
  298. }
  299. else if (epoch >= 5)
  300. {
  301. if (m_imageRemainCallback.isCallable())
  302. {
  303. QJSValueList args;
  304. args << getImageUrl();
  305. m_imageRemainCallback.call(args);
  306. }
  307. }
  308. }
  309. else if (res == MOK && detectedFaces.faceNum >= 2)
  310. {
  311. isAppear = true;
  312. m_laseCount--;
  313. painter.setPen(QPen(Qt::red, 3));
  314. painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
  315. Qt::AlignCenter,
  316. QString("请保持单人入镜,请保持光线充足"));
  317. }
  318. else
  319. {
  320. isAppear = false;
  321. m_laseCount--;
  322. painter.setPen(QPen(Qt::red, 3));
  323. painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
  324. Qt::AlignCenter,
  325. QString("请保持真人操作,请保持光线充足"));
  326. }
  327. if (m_isAppearCallback.isCallable())
  328. {
  329. QJSValueList args;
  330. args << isAppear;
  331. m_isAppearCallback.call(args);
  332. }
  333. }
  334. }
  335. painter.end();
  336. m_image = image.copy();
  337. if (m_imageGatherCallback.isCallable())
  338. {
  339. QJSValueList args;
  340. args << getImageUrl();
  341. m_imageGatherCallback.call(args);
  342. }
  343. }
  344. }
  345. }
  346. }
  347. // 获取图像
  348. QImage InteractiveFace::getImage()
  349. {
  350. QMutexLocker locker(&m_mutex);
  351. return m_image.copy();
  352. }