index_3660.html 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width,initial-scale=1">
  6. <title>ESP32 OV3660</title>
  7. <style>
  8. body {
  9. font-family: Arial,Helvetica,sans-serif;
  10. background: #181818;
  11. color: #EFEFEF;
  12. font-size: 16px
  13. }
  14. h2 {
  15. font-size: 18px
  16. }
  17. section.main {
  18. display: flex
  19. }
  20. #menu,section.main {
  21. flex-direction: column
  22. }
  23. #menu {
  24. display: none;
  25. flex-wrap: nowrap;
  26. min-width: 340px;
  27. background: #363636;
  28. padding: 8px;
  29. border-radius: 4px;
  30. margin-top: -10px;
  31. margin-right: 10px;
  32. }
  33. #content {
  34. display: flex;
  35. flex-wrap: wrap;
  36. align-items: stretch
  37. }
  38. figure {
  39. padding: 0px;
  40. margin: 0;
  41. -webkit-margin-before: 0;
  42. margin-block-start: 0;
  43. -webkit-margin-after: 0;
  44. margin-block-end: 0;
  45. -webkit-margin-start: 0;
  46. margin-inline-start: 0;
  47. -webkit-margin-end: 0;
  48. margin-inline-end: 0
  49. }
  50. figure img {
  51. display: block;
  52. width: 100%;
  53. height: auto;
  54. border-radius: 4px;
  55. margin-top: 8px;
  56. }
  57. @media (min-width: 800px) and (orientation:landscape) {
  58. #content {
  59. display:flex;
  60. flex-wrap: nowrap;
  61. align-items: stretch
  62. }
  63. figure img {
  64. display: block;
  65. max-width: 100%;
  66. max-height: calc(100vh - 40px);
  67. width: auto;
  68. height: auto
  69. }
  70. figure {
  71. padding: 0 0 0 0px;
  72. margin: 0;
  73. -webkit-margin-before: 0;
  74. margin-block-start: 0;
  75. -webkit-margin-after: 0;
  76. margin-block-end: 0;
  77. -webkit-margin-start: 0;
  78. margin-inline-start: 0;
  79. -webkit-margin-end: 0;
  80. margin-inline-end: 0
  81. }
  82. }
  83. section#buttons {
  84. display: flex;
  85. flex-wrap: nowrap;
  86. justify-content: space-between
  87. }
  88. #nav-toggle {
  89. cursor: pointer;
  90. display: block
  91. }
  92. #nav-toggle-cb {
  93. outline: 0;
  94. opacity: 0;
  95. width: 0;
  96. height: 0
  97. }
  98. #nav-toggle-cb:checked+#menu {
  99. display: flex
  100. }
  101. .input-group {
  102. display: flex;
  103. flex-wrap: nowrap;
  104. line-height: 22px;
  105. margin: 5px 0
  106. }
  107. .input-group>label {
  108. display: inline-block;
  109. padding-right: 10px;
  110. min-width: 47%
  111. }
  112. .input-group input,.input-group select {
  113. flex-grow: 1
  114. }
  115. .range-max,.range-min {
  116. display: inline-block;
  117. padding: 0 5px
  118. }
  119. button {
  120. display: block;
  121. margin: 5px;
  122. padding: 0 12px;
  123. border: 0;
  124. line-height: 28px;
  125. cursor: pointer;
  126. color: #fff;
  127. background: #ff3034;
  128. border-radius: 5px;
  129. font-size: 16px;
  130. outline: 0
  131. }
  132. button:hover {
  133. background: #ff494d
  134. }
  135. button:active {
  136. background: #f21c21
  137. }
  138. button.disabled {
  139. cursor: default;
  140. background: #a0a0a0
  141. }
  142. input[type=range] {
  143. -webkit-appearance: none;
  144. width: 100%;
  145. height: 22px;
  146. background: #363636;
  147. cursor: pointer;
  148. margin: 0
  149. }
  150. input[type=range]:focus {
  151. outline: 0
  152. }
  153. input[type=range]::-webkit-slider-runnable-track {
  154. width: 100%;
  155. height: 2px;
  156. cursor: pointer;
  157. background: #EFEFEF;
  158. border-radius: 0;
  159. border: 0 solid #EFEFEF
  160. }
  161. input[type=range]::-webkit-slider-thumb {
  162. border: 1px solid rgba(0,0,30,0);
  163. height: 22px;
  164. width: 22px;
  165. border-radius: 50px;
  166. background: #ff3034;
  167. cursor: pointer;
  168. -webkit-appearance: none;
  169. margin-top: -11.5px
  170. }
  171. input[type=range]:focus::-webkit-slider-runnable-track {
  172. background: #EFEFEF
  173. }
  174. input[type=range]::-moz-range-track {
  175. width: 100%;
  176. height: 2px;
  177. cursor: pointer;
  178. background: #EFEFEF;
  179. border-radius: 0;
  180. border: 0 solid #EFEFEF
  181. }
  182. input[type=range]::-moz-range-thumb {
  183. border: 1px solid rgba(0,0,30,0);
  184. height: 22px;
  185. width: 22px;
  186. border-radius: 50px;
  187. background: #ff3034;
  188. cursor: pointer
  189. }
  190. input[type=range]::-ms-track {
  191. width: 100%;
  192. height: 2px;
  193. cursor: pointer;
  194. background: 0 0;
  195. border-color: transparent;
  196. color: transparent
  197. }
  198. input[type=range]::-ms-fill-lower {
  199. background: #EFEFEF;
  200. border: 0 solid #EFEFEF;
  201. border-radius: 0
  202. }
  203. input[type=range]::-ms-fill-upper {
  204. background: #EFEFEF;
  205. border: 0 solid #EFEFEF;
  206. border-radius: 0
  207. }
  208. input[type=range]::-ms-thumb {
  209. border: 1px solid rgba(0,0,30,0);
  210. height: 22px;
  211. width: 22px;
  212. border-radius: 50px;
  213. background: #ff3034;
  214. cursor: pointer;
  215. height: 2px
  216. }
  217. input[type=range]:focus::-ms-fill-lower {
  218. background: #EFEFEF
  219. }
  220. input[type=range]:focus::-ms-fill-upper {
  221. background: #363636
  222. }
  223. .switch {
  224. display: block;
  225. position: relative;
  226. line-height: 22px;
  227. font-size: 16px;
  228. height: 22px
  229. }
  230. .switch input {
  231. outline: 0;
  232. opacity: 0;
  233. width: 0;
  234. height: 0
  235. }
  236. .slider {
  237. width: 50px;
  238. height: 22px;
  239. border-radius: 22px;
  240. cursor: pointer;
  241. background-color: grey
  242. }
  243. .slider,.slider:before {
  244. display: inline-block;
  245. transition: .4s
  246. }
  247. .slider:before {
  248. position: relative;
  249. content: "";
  250. border-radius: 50%;
  251. height: 16px;
  252. width: 16px;
  253. left: 4px;
  254. top: 3px;
  255. background-color: #fff
  256. }
  257. input:checked+.slider {
  258. background-color: #ff3034
  259. }
  260. input:checked+.slider:before {
  261. -webkit-transform: translateX(26px);
  262. transform: translateX(26px)
  263. }
  264. select {
  265. border: 1px solid #363636;
  266. font-size: 14px;
  267. height: 22px;
  268. outline: 0;
  269. border-radius: 5px
  270. }
  271. .image-container {
  272. position: relative;
  273. min-width: 160px
  274. }
  275. .close {
  276. position: absolute;
  277. right: 5px;
  278. top: 5px;
  279. background: #ff3034;
  280. width: 16px;
  281. height: 16px;
  282. border-radius: 100px;
  283. color: #fff;
  284. text-align: center;
  285. line-height: 18px;
  286. cursor: pointer
  287. }
  288. .hidden {
  289. display: none
  290. }
  291. input[type=text] {
  292. border: 1px solid #363636;
  293. font-size: 14px;
  294. height: 20px;
  295. margin: 1px;
  296. outline: 0;
  297. border-radius: 5px
  298. }
  299. .inline-button {
  300. line-height: 20px;
  301. margin: 2px;
  302. padding: 1px 4px 2px 4px;
  303. }
  304. </style>
  305. </head>
  306. <body>
  307. <section class="main">
  308. <div id="logo">
  309. <label for="nav-toggle-cb" id="nav-toggle">&#9776;&nbsp;&nbsp;Toggle OV3660 settings</label>
  310. </div>
  311. <div id="content">
  312. <div id="sidebar">
  313. <input type="checkbox" id="nav-toggle-cb" checked="checked">
  314. <nav id="menu">
  315. <div class="input-group" id="framesize-group">
  316. <label for="framesize">Resolution</label>
  317. <select id="framesize" class="default-action">
  318. <option value="11">QXGA(2048x1564)</option>
  319. <option value="10">UXGA(1600x1200)</option>
  320. <option value="9">SXGA(1280x1024)</option>
  321. <option value="8">XGA(1024x768)</option>
  322. <option value="7">SVGA(800x600)</option>
  323. <option value="6">VGA(640x480)</option>
  324. <option value="5" selected="selected">CIF(400x296)</option>
  325. <option value="4">QVGA(320x240)</option>
  326. <option value="3">HQVGA(240x176)</option>
  327. <option value="0">QQVGA(160x120)</option>
  328. </select>
  329. </div>
  330. <div class="input-group" id="quality-group">
  331. <label for="quality">Quality</label>
  332. <div class="range-min">4</div>
  333. <input type="range" id="quality" min="4" max="63" value="10" class="default-action">
  334. <div class="range-max">63</div>
  335. </div>
  336. <div class="input-group" id="brightness-group">
  337. <label for="brightness">Brightness</label>
  338. <div class="range-min">-3</div>
  339. <input type="range" id="brightness" min="-3" max="3" value="0" class="default-action">
  340. <div class="range-max">3</div>
  341. </div>
  342. <div class="input-group" id="contrast-group">
  343. <label for="contrast">Contrast</label>
  344. <div class="range-min">-3</div>
  345. <input type="range" id="contrast" min="-3" max="3" value="0" class="default-action">
  346. <div class="range-max">3</div>
  347. </div>
  348. <div class="input-group" id="saturation-group">
  349. <label for="saturation">Saturation</label>
  350. <div class="range-min">-4</div>
  351. <input type="range" id="saturation" min="-4" max="4" value="0" class="default-action">
  352. <div class="range-max">4</div>
  353. </div>
  354. <div class="input-group" id="sharpness-group">
  355. <label for="sharpness">Sharpness</label>
  356. <div class="range-min">-3</div>
  357. <input type="range" id="sharpness" min="-3" max="3" value="0" class="default-action">
  358. <div class="range-max">3</div>
  359. </div>
  360. <div class="input-group" id="denoise-group">
  361. <label for="denoise">De-Noise</label>
  362. <div class="range-min">Auto</div>
  363. <input type="range" id="denoise" min="0" max="8" value="0" class="default-action">
  364. <div class="range-max">8</div>
  365. </div>
  366. <div class="input-group" id="ae_level-group">
  367. <label for="ae_level">Exposure Level</label>
  368. <div class="range-min">-5</div>
  369. <input type="range" id="ae_level" min="-5" max="5" value="0" class="default-action">
  370. <div class="range-max">5</div>
  371. </div>
  372. <div class="input-group" id="gainceiling-group">
  373. <label for="gainceiling">Gainceiling</label>
  374. <div class="range-min">0</div>
  375. <input type="range" id="gainceiling" min="0" max="511" value="0" class="default-action">
  376. <div class="range-max">511</div>
  377. </div>
  378. <div class="input-group" id="special_effect-group">
  379. <label for="special_effect">Special Effect</label>
  380. <select id="special_effect" class="default-action">
  381. <option value="0" selected="selected">No Effect</option>
  382. <option value="1">Negative</option>
  383. <option value="2">Grayscale</option>
  384. <option value="3">Red Tint</option>
  385. <option value="4">Green Tint</option>
  386. <option value="5">Blue Tint</option>
  387. <option value="6">Sepia</option>
  388. </select>
  389. </div>
  390. <div class="input-group" id="awb-group">
  391. <label for="awb">AWB Enable</label>
  392. <div class="switch">
  393. <input id="awb" type="checkbox" class="default-action" checked="checked">
  394. <label class="slider" for="awb"></label>
  395. </div>
  396. </div>
  397. <div class="input-group" id="dcw-group">
  398. <label for="dcw">Advanced AWB</label>
  399. <div class="switch">
  400. <input id="dcw" type="checkbox" class="default-action" checked="checked">
  401. <label class="slider" for="dcw"></label>
  402. </div>
  403. </div>
  404. <div class="input-group" id="awb_gain-group">
  405. <label for="awb_gain">Manual AWB</label>
  406. <div class="switch">
  407. <input id="awb_gain" type="checkbox" class="default-action" checked="checked">
  408. <label class="slider" for="awb_gain"></label>
  409. </div>
  410. </div>
  411. <div class="input-group" id="wb_mode-group">
  412. <label for="wb_mode">AWB Mode</label>
  413. <select id="wb_mode" class="default-action">
  414. <option value="0" selected="selected">Auto</option>
  415. <option value="1">Sunny</option>
  416. <option value="2">Cloudy</option>
  417. <option value="3">Office</option>
  418. <option value="4">Home</option>
  419. </select>
  420. </div>
  421. <div class="input-group" id="aec-group">
  422. <label for="aec">AEC Enable</label>
  423. <div class="switch">
  424. <input id="aec" type="checkbox" class="default-action" checked="checked">
  425. <label class="slider" for="aec"></label>
  426. </div>
  427. </div>
  428. <div class="input-group" id="aec_value-group">
  429. <label for="aec_value">Manual Exposure</label>
  430. <div class="range-min">0</div>
  431. <input type="range" id="aec_value" min="0" max="1536" value="320" class="default-action">
  432. <div class="range-max">1536</div>
  433. </div>
  434. <div class="input-group" id="aec2-group">
  435. <label for="aec2">Night Mode</label>
  436. <div class="switch">
  437. <input id="aec2" type="checkbox" class="default-action" checked="checked">
  438. <label class="slider" for="aec2"></label>
  439. </div>
  440. </div>
  441. <div class="input-group" id="agc-group">
  442. <label for="agc">AGC</label>
  443. <div class="switch">
  444. <input id="agc" type="checkbox" class="default-action" checked="checked">
  445. <label class="slider" for="agc"></label>
  446. </div>
  447. </div>
  448. <div class="input-group hidden" id="agc_gain-group">
  449. <label for="agc_gain">Gain</label>
  450. <div class="range-min">1x</div>
  451. <input type="range" id="agc_gain" min="0" max="64" value="5" class="default-action">
  452. <div class="range-max">64x</div>
  453. </div>
  454. <div class="input-group" id="raw_gma-group">
  455. <label for="raw_gma">GMA Enable</label>
  456. <div class="switch">
  457. <input id="raw_gma" type="checkbox" class="default-action" checked="checked">
  458. <label class="slider" for="raw_gma"></label>
  459. </div>
  460. </div>
  461. <div class="input-group" id="lenc-group">
  462. <label for="lenc">Lens Correction</label>
  463. <div class="switch">
  464. <input id="lenc" type="checkbox" class="default-action" checked="checked">
  465. <label class="slider" for="lenc"></label>
  466. </div>
  467. </div>
  468. <div class="input-group" id="hmirror-group">
  469. <label for="hmirror">H-Mirror</label>
  470. <div class="switch">
  471. <input id="hmirror" type="checkbox" class="default-action" checked="checked">
  472. <label class="slider" for="hmirror"></label>
  473. </div>
  474. </div>
  475. <div class="input-group" id="vflip-group">
  476. <label for="vflip">V-Flip</label>
  477. <div class="switch">
  478. <input id="vflip" type="checkbox" class="default-action" checked="checked">
  479. <label class="slider" for="vflip"></label>
  480. </div>
  481. </div>
  482. <div class="input-group" id="bpc-group">
  483. <label for="bpc">BPC</label>
  484. <div class="switch">
  485. <input id="bpc" type="checkbox" class="default-action">
  486. <label class="slider" for="bpc"></label>
  487. </div>
  488. </div>
  489. <div class="input-group" id="wpc-group">
  490. <label for="wpc">WPC</label>
  491. <div class="switch">
  492. <input id="wpc" type="checkbox" class="default-action" checked="checked">
  493. <label class="slider" for="wpc"></label>
  494. </div>
  495. </div>
  496. <div class="input-group" id="colorbar-group">
  497. <label for="colorbar">Color Bar</label>
  498. <div class="switch">
  499. <input id="colorbar" type="checkbox" class="default-action">
  500. <label class="slider" for="colorbar"></label>
  501. </div>
  502. </div>
  503. <div class="input-group" id="face_detect-group">
  504. <label for="face_detect">Face Detection</label>
  505. <div class="switch">
  506. <input id="face_detect" type="checkbox" class="default-action">
  507. <label class="slider" for="face_detect"></label>
  508. </div>
  509. </div>
  510. <div class="input-group" id="face_recognize-group">
  511. <label for="face_recognize">Face Recognition</label>
  512. <div class="switch">
  513. <input id="face_recognize" type="checkbox" class="default-action">
  514. <label class="slider" for="face_recognize"></label>
  515. </div>
  516. </div>
  517. <section id="buttons">
  518. <button id="get-still">Get Still</button>
  519. <button id="toggle-stream">Start Stream</button>
  520. <button id="face_enroll" class="disabled" disabled="disabled">Enroll Face</button>
  521. </section>
  522. </nav>
  523. </div>
  524. <figure>
  525. <div id="stream-container" class="image-container hidden">
  526. <div class="close" id="close-stream">×</div>
  527. <img id="stream" src="">
  528. </div>
  529. </figure>
  530. </div>
  531. </section>
  532. <script>
  533. document.addEventListener('DOMContentLoaded', function (event) {
  534. var baseHost = document.location.origin
  535. var streamUrl = baseHost + ':81'
  536. const hide = el => {
  537. el.classList.add('hidden')
  538. }
  539. const show = el => {
  540. el.classList.remove('hidden')
  541. }
  542. const disable = el => {
  543. el.classList.add('disabled')
  544. el.disabled = true
  545. }
  546. const enable = el => {
  547. el.classList.remove('disabled')
  548. el.disabled = false
  549. }
  550. const updateValue = (el, value, updateRemote) => {
  551. updateRemote = updateRemote == null ? true : updateRemote
  552. let initialValue
  553. if (el.type === 'checkbox') {
  554. initialValue = el.checked
  555. value = !!value
  556. el.checked = value
  557. } else {
  558. initialValue = el.value
  559. el.value = value
  560. }
  561. if (updateRemote && initialValue !== value) {
  562. updateConfig(el);
  563. } else if(!updateRemote){
  564. if(el.id === "aec"){
  565. value ? hide(exposure) : show(exposure)
  566. } else if(el.id === "agc"){
  567. if (value) {
  568. hide(agcGain)
  569. } else {
  570. show(agcGain)
  571. }
  572. } else if(el.id === "awb_gain"){
  573. value ? show(wb) : hide(wb)
  574. } else if(el.id === "face_recognize"){
  575. value ? enable(enrollButton) : disable(enrollButton)
  576. }
  577. }
  578. }
  579. function updateConfig (el) {
  580. let value
  581. switch (el.type) {
  582. case 'checkbox':
  583. value = el.checked ? 1 : 0
  584. break
  585. case 'range':
  586. case 'select-one':
  587. value = el.value
  588. break
  589. case 'button':
  590. case 'submit':
  591. value = '1'
  592. break
  593. default:
  594. return
  595. }
  596. const query = `${baseHost}/control?var=${el.id}&val=${value}`
  597. fetch(query)
  598. .then(response => {
  599. console.log(`request to ${query} finished, status: ${response.status}`)
  600. })
  601. }
  602. document
  603. .querySelectorAll('.close')
  604. .forEach(el => {
  605. el.onclick = () => {
  606. hide(el.parentNode)
  607. }
  608. })
  609. // read initial values
  610. fetch(`${baseHost}/status`)
  611. .then(function (response) {
  612. return response.json()
  613. })
  614. .then(function (state) {
  615. document
  616. .querySelectorAll('.default-action')
  617. .forEach(el => {
  618. updateValue(el, state[el.id], false)
  619. })
  620. })
  621. const view = document.getElementById('stream')
  622. const viewContainer = document.getElementById('stream-container')
  623. const stillButton = document.getElementById('get-still')
  624. const streamButton = document.getElementById('toggle-stream')
  625. const enrollButton = document.getElementById('face_enroll')
  626. const closeButton = document.getElementById('close-stream')
  627. const stopStream = () => {
  628. window.stop();
  629. streamButton.innerHTML = 'Start Stream'
  630. }
  631. const startStream = () => {
  632. view.src = `${streamUrl}/stream`
  633. show(viewContainer)
  634. streamButton.innerHTML = 'Stop Stream'
  635. }
  636. // Attach actions to buttons
  637. stillButton.onclick = () => {
  638. stopStream()
  639. view.src = `${baseHost}/capture?_cb=${Date.now()}`
  640. show(viewContainer)
  641. }
  642. closeButton.onclick = () => {
  643. stopStream()
  644. hide(viewContainer)
  645. }
  646. streamButton.onclick = () => {
  647. const streamEnabled = streamButton.innerHTML === 'Stop Stream'
  648. if (streamEnabled) {
  649. stopStream()
  650. } else {
  651. startStream()
  652. }
  653. }
  654. enrollButton.onclick = () => {
  655. updateConfig(enrollButton)
  656. }
  657. // Attach default on change action
  658. document
  659. .querySelectorAll('.default-action')
  660. .forEach(el => {
  661. el.onchange = () => updateConfig(el)
  662. })
  663. // Custom actions
  664. // Gain
  665. const agc = document.getElementById('agc')
  666. const agcGain = document.getElementById('agc_gain-group')
  667. agc.onchange = () => {
  668. updateConfig(agc)
  669. if (agc.checked) {
  670. hide(agcGain)
  671. } else {
  672. show(agcGain)
  673. }
  674. }
  675. // Exposure
  676. const aec = document.getElementById('aec')
  677. const exposure = document.getElementById('aec_value-group')
  678. aec.onchange = () => {
  679. updateConfig(aec)
  680. aec.checked ? hide(exposure) : show(exposure)
  681. }
  682. // AWB
  683. const awb = document.getElementById('awb_gain')
  684. const wb = document.getElementById('wb_mode-group')
  685. awb.onchange = () => {
  686. updateConfig(awb)
  687. awb.checked ? show(wb) : hide(wb)
  688. }
  689. // Detection and framesize
  690. const detect = document.getElementById('face_detect')
  691. const recognize = document.getElementById('face_recognize')
  692. const framesize = document.getElementById('framesize')
  693. framesize.onchange = () => {
  694. updateConfig(framesize)
  695. if (framesize.value > 5) {
  696. updateValue(detect, false)
  697. updateValue(recognize, false)
  698. }
  699. }
  700. detect.onchange = () => {
  701. if (framesize.value > 5) {
  702. alert("Please select CIF or lower resolution before enabling this feature!");
  703. updateValue(detect, false)
  704. return;
  705. }
  706. updateConfig(detect)
  707. if (!detect.checked) {
  708. disable(enrollButton)
  709. updateValue(recognize, false)
  710. }
  711. }
  712. recognize.onchange = () => {
  713. if (framesize.value > 5) {
  714. alert("Please select CIF or lower resolution before enabling this feature!");
  715. updateValue(recognize, false)
  716. return;
  717. }
  718. updateConfig(recognize)
  719. if (recognize.checked) {
  720. enable(enrollButton)
  721. updateValue(detect, true)
  722. } else {
  723. disable(enrollButton)
  724. }
  725. }
  726. })
  727. </script>
  728. </body>
  729. </html>