国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流

這篇具有很好參考價(jià)值的文章主要介紹了Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、業(yè)務(wù)需求和調(diào)研

1. 現(xiàn)有的平臺(tái)系統(tǒng)播放實(shí)時(shí)視頻。

因?yàn)橛脩綦娔X都是Linux系統(tǒng),無法直接使用??登岸薙DK,討論決定由后臺(tái)推視頻流,簡單調(diào)研后發(fā)現(xiàn)最流行的是flv,而且有B站開源的flv.js適配。前期后臺(tái)推給我RTMP前綴的視頻流,我嘗試使用video.js,西瓜視頻等都失敗了,后來后端改為http前綴的,對接成功。這里還要講一下flv.js的文檔, 不知道是我理解有誤, 還是文檔沒有更新, 還是讓人一身冷汗的:

Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流,業(yè)務(wù)需求解決方案,javascript,vue.js,音視頻,前端

第二句講: FLV實(shí)時(shí)流在所有瀏覽器無法工作

但是點(diǎn)進(jìn)去livestream.md:

Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流,業(yè)務(wù)需求解決方案,javascript,vue.js,音視頻,前端

這里又講: 根據(jù)IO限制, flv.js目前在各類新版瀏覽器支持HTTP FLV實(shí)時(shí)流

總而言之,即便是chrome已經(jīng)不支持flash,但是用B站這款flv.js還是可以實(shí)現(xiàn)在現(xiàn)代瀏覽器播放HTTP FLV視頻流的。

2. 分屏,先點(diǎn)擊分屏,然后選擇需要播放的視頻設(shè)備,在該分屏播放對應(yīng)的視頻流。

3. 開啟新的視頻的同時(shí),以及離開本頁面時(shí)要關(guān)閉之前的視頻流,以減輕服務(wù)器壓力。這一點(diǎn)跟主流需求還是很不同的,因?yàn)橥ǔ6紩?huì)理解為在分屏可以同時(shí)觀看多個(gè)攝像頭的實(shí)時(shí)畫面,所以即使我已經(jīng)實(shí)現(xiàn)了需求,但還是感覺分屏在這里是有些雞肋的。

二、實(shí)現(xiàn)效果

這里展示4屏和6屏,1屏就不用展示了,下面代碼中還有9屏和16屏可選,目前我這里用不到,就先注釋掉了。

Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流,業(yè)務(wù)需求解決方案,javascript,vue.js,音視頻,前端

Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流,業(yè)務(wù)需求解決方案,javascript,vue.js,音視頻,前端

三、鳴謝

感謝二位大佬的解決方案,這是我實(shí)現(xiàn)本業(yè)務(wù)需求的基礎(chǔ):

ID:?抄一下你代碼

全網(wǎng)最詳細(xì)!vue中使用flv.js 播放直播監(jiān)控視頻流

ID:?三體人1379號(hào)

vue實(shí)現(xiàn)視頻播放1,4,6,9,16宮格布局文章來源地址http://www.zghlxwxcb.cn/news/detail-769118.html

四、代碼實(shí)現(xiàn)

1. 子組件, 也就是視頻播放器,您也可以根據(jù)不同的視頻流資源配置不同的播放器:
<template>
  <div :class="{ player: true, selected: isSelected }" @click="handlePlayerClick">
    <!-- {{ title }}號(hào)窗口 -->
    <video
      class="cell-player-1"
      ref="videosmallone"
      preload="auto"
      muted
      controls
      autoplay
      type="rtmp/flv"
    >
      <source src="" />
    </video>
  </div>
</template>

<script>
import flvjs from 'flv.js'

export default {
  props: {
    title: {
      type: Number,
      default: 1
    },
    activePlayer: {
      type: Number,
      default: null
    }
  },
  data() {
    return {
      player: null,
      loading: false,
      videoUrl: '',
      videoToken: ''
    }
  },
  beforeUnmount() {
    if (this.player) {
      this.player.pause()
      this.player.unload()
      this.player.detachMediaElement()
      this.player.destroy()
      this.player = null
    }
  },
  computed: {
    // Use a computed property to determine if the player is active
    isSelected() {
      return this.activePlayer === this.title
    },
    playerClass() {
      return ['player', `cell-player-1`, { active: this.title === this.activePlayer }]
    }
  },
  methods: {
    handlePlayerClick() {
      // 在點(diǎn)擊事件中調(diào)用父組件的方法,傳遞數(shù)據(jù)
      this.$emit('playerClick', this.title)
      // console.log('class', this.playerClass)
    },
    openVideo(data) {
      // Implement this method to update the data in the player component
      // Use the passed data to update the player's state or perform other operations
      // console.log(`Setting data for player ${this.title}:`, data)
      this.init(data.data.url)
    },
    init(val) {
      //這個(gè)val 就是一個(gè)地址,例如: http://192.168.2.201:85/live/9311272c49b845baa2b2810ad9bf3f68.flv 這是個(gè)服務(wù)器返回給我的一個(gè)監(jiān)控視頻流地址
      setTimeout(() => {
        //使用定時(shí)器是因?yàn)?,在mounted聲明周期里調(diào)用,可能會(huì)出現(xiàn)DOM沒加載出來的原因
        var videoElement = this.$refs.videosmallone // 獲取到html中的video標(biāo)簽
        if (flvjs.isSupported()) {
          //因?yàn)槲疫@個(gè)是復(fù)用組件,進(jìn)來先判斷 player是否存在,如果存在,銷毀掉它,不然會(huì)占用TCP名額
          if (this.player !== null) {
            this.player.pause()
            this.player.unload()
            this.player.detachMediaElement()
            this.player.destroy()
            this.player = null
          }
          this.player = flvjs.createPlayer(
            //創(chuàng)建直播流,加載到DOM中去
            {
              type: 'flv',
              url: val, //你的url地址
              isLive: true, //數(shù)據(jù)源是否為直播流
              hasAudio: false, //數(shù)據(jù)源是否包含有音頻
              hasVideo: true, //數(shù)據(jù)源是否包含有視頻
              enableStashBuffer: true //是否啟用緩存區(qū)
            },
            {
              enableWorker: false, //不啟用分離線程
              enableStashBuffer: false, //關(guān)閉IO隱藏緩沖區(qū)
              autoCleanupSourceBuffer: true, //自動(dòng)清除緩存
              lazyLoad: false
            }
          )
          this.player.attachMediaElement(videoElement) //放到dom中去
          this.player.load() //準(zhǔn)備完成
          //!!!!!!這里需要注意,有的時(shí)候load加載完成不一定可以播放,要是播放不成功,用settimeout 給下面的this.player.play() 延時(shí)幾百毫秒再播放
          this.player.play() //播放
        }
      }, 1000)
    }
  }
}
</script>

<style scoped>
.player {
  background-color: black;
  height: 100%;
  border: 1px solid grey;
  color: white;
  text-align: center;
}
.selected {
  background-color: black;
  height: 100%;
  border: 2px solid green;
  color: white;
  text-align: center;
}

.cell-player-1 {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
</style>
2. 父組件結(jié)構(gòu):
<template>
  <div style="height: 100%">
    <a-form layout="inline" class="header">
      <a-form-item>
        <div class="cell-tool">
          <div class="bk-button-group">
            <a-button
              :class="{ active: cellCount === 1 }"
              @click="cellCount = 1"
              style="margin-right: 5px"
              >1屏</a-button
            >
            <a-button
              :class="{ active: cellCount === 4 }"
              @click="cellCount = 4"
              style="margin-right: 5px"
              >4屏</a-button
            >
            <a-button
              :class="{ active: cellCount === 6 }"
              @click="cellCount = 6"
              style="margin-right: 5px"
              >6屏</a-button
            >
            <!-- <button @click="cellCount = 9" size="small">9</button>
            <button @click="cellCount = 16" size="small">16</button> -->
          </div>
        </div>
      </a-form-item>
      <a-form-item label="選擇設(shè)備:">
        <a-tree-select
          v-model="value"
          style="width: 200px"
          :dropdown-style="{ maxHeight: '600px', overflow: 'auto' }"
          :tree-data="treeData"
          placeholder="請選擇設(shè)備"
          :treeDefaultExpandAll="true"
        >
        </a-tree-select>
      </a-form-item>

      <a-form-item>
        <div style="display: inline-block">
          <SavaButton type="search" @click="playRealtimeVideo">播放</SavaButton>
          <SavaButton type="delete" @click="resetSearchForm()" style="margin-left: 8px"
            >重置</SavaButton
          >
        </div>
      </a-form-item>
    </a-form>
    <div class="main-body">
      <div class="left">
        <div class="left-upper"></div>
        <div class="left-lower"></div>
      </div>
      <div class="right">
        <!-- 然后在這里添加分屏的布局 -->
        <div class="cell">
          <div class="cell-player">
            <div :class="cellClass(i)" v-for="i in cellCount" :key="i">
              <player
                :title="i"
                @playerClick="handlePlayerClick"
                v-if="cellCount != 6"
                :activePlayer="activePlayer"
                :ref="`player${i}`"
              ></player>
              <player
                :title="i"
                @playerClick="handlePlayerClick"
                v-if="cellCount == 6 && i != 2 && i != 3"
                :activePlayer="activePlayer"
                :ref="`player${i}`"
              ></player>
              <template v-if="cellCount == 6 && i == 2">
                <div class="cell-player-6-2-cell">
                  <player
                    :title="i"
                    @playerClick="handlePlayerClick"
                    :activePlayer="activePlayer"
                    :ref="`player${i}`"
                  ></player>
                  <!-- original config is ++i -->
                  <player
                    :title="i + 1"
                    @playerClick="handlePlayerClick"
                    :activePlayer="activePlayer"
                    :ref="`player${i + 1}`"
                  ></player>
                </div>
              </template>
            </div>
          </div>
        </div>
        <div class="right-lower"></div>
      </div>
    </div>
  </div>
</template>
3. 核心業(yè)務(wù)邏輯:
<script>
import player from './player/player.vue'
import { reqStationAndCamera, reqGetRealtimeVideo, reqCloseVideo1 } from '@/api/camera'
export default {
  components: { player },
  data() {
    return {
      queryParam: {
        id: ''
      },
      cellCount: 1,
      value: '',
      treeData: [],
      activePlayer: 1,
      oldToken: '', // 保存已經(jīng)開啟視頻的token, 用于關(guān)閉視頻
      oldTokensArray: []
    }
  },
  created() {
    this.getStationAndCamera()
  },
  mounted() {
    // Add the beforeunload event listener when the component is mounted
    window.addEventListener('beforeunload', this.closeOldVideos)
  },
  beforeUnmount() {
    // This method will be called before the component is unmounted or the page is unloaded
    this.closeOldVideos()
    // Remove the beforeunload event listener before the component is unmounted
    window.removeEventListener('beforeunload', this.closeOldVideos)
  },
  watch: {
    value(value) {
      console.log(value)
    }
  },
  methods: {
    changeScreen() {
      // 處理切換分屏的邏輯
    },
    // 這里是整理數(shù)據(jù)用于下拉框選擇播放視頻源的設(shè)備
    getStationAndCamera() {
      reqStationAndCamera({ city: '', camera: 1 }).then((res) => {
        // 創(chuàng)建一個(gè)空數(shù)組用于存儲(chǔ)treeData
        const treeData = []

        // 遍歷后臺(tái)返回的數(shù)組
        res.forEach((station) => {
          // 提取一級(jí)菜單的信息
          const firstLevelNode = {
            title: station.stationName,
            value: station.id,
            key: `level1-${station.id}`, // 使用id作為key
            disabled: true, // 設(shè)置一級(jí)菜單為不可選
            children: [] // 用于存儲(chǔ)二級(jí)菜單
          }

          // 遍歷devices數(shù)組,提取二級(jí)菜單的信息
          station.devices.forEach((device) => {
            const secondLevelNode = {
              title: device.deviceName,
              value: device.id,
              key: `level2-${device.id}` // 使用id作為key
              // 如果有三級(jí)菜單,可以在這里繼續(xù)處理
            }

            // 將二級(jí)菜單添加到一級(jí)菜單的children數(shù)組中
            firstLevelNode.children.push(secondLevelNode)
          })

          // 將一級(jí)菜單添加到treeData數(shù)組中
          treeData.push(firstLevelNode)
        })

        // 打印加工后的treeData
        console.log('Processed treeData:', treeData)
        this.treeData = treeData
      })
    },

    async playRealtimeVideo() {
      if (!this.value) {
        this.$message.error('請選擇設(shè)備')

        // 中止程序,可以使用return或者throw語句,根據(jù)您的需求選擇
        return // 中止程序執(zhí)行
      } else {
        this.queryParam = {
          id: this.value
        }
      }

      // console.log('realtime video param', this.queryParam)

      const RealtimeVideoParams = this.queryParam
      const playerRef = `player${this.activePlayer}`

      // 使用 $refs 引用 player 組件實(shí)例
      const playerInstance = this.$refs[playerRef]
      // console.log('playerInstance:', playerInstance)

      try {
        const res = await this.getRealtimeVideo(RealtimeVideoParams)

        // Check if 'res' is undefined or not
        if (res !== undefined) {
          console.log('new data res', res)
          this.$message.success('獲取視頻成功, 正在打開', 5)

          const newDataForClickedPlayer = res

          console.log('newDataForClickedPlayer:', newDataForClickedPlayer)

          if (playerInstance) {
            // Pass data to the newly clicked player
            playerInstance[0].openVideo(newDataForClickedPlayer)

            // Check if there was a previously clicked player
            if (this.activePlayer !== null) {
              // console.log('active player', this.activePlayer)
              // Perform any operations specific to the previously clicked player
              // playerInstance[0].closeVideo(historyVideoData)
            }
          }

          this.closeOldVideos()
        }
        this.oldToken = res.data.token
      } catch (error) {
        console.error('Error in play realtime video:', error)
      }
    },
    resetSearchForm() {
      this.value = ''
      this.queryParam = {
        id: ''
      }
    },
    getRealtimeVideo(queryParam) {
      return new Promise((resolve, reject) => {
        reqGetRealtimeVideo(queryParam)
          .then((res) => {
            console.log('realtime video', res)
            resolve(res)
          })
          .catch((error) => {
            console.error('Error fetching realtime video:', error)
            reject(error)
          })
      })
    },
    handlePlayerClick(title) {
      // console.log('clicked window', title)

      // Update the active player in the parent component
      this.activePlayer = title
      // console.log('active player', this.activePlayer)
    },
    closeOldVideos() {
      if (this.oldToken) {
        this.oldTokensArray.push(this.oldToken)

        // Map old tokens array to an array of promises
        const closePromises = this.oldTokensArray.map((oldToken) =>
          reqCloseVideo1(oldToken)
            .then((resc) => {
              console.log('close old video', resc)
              this.$message.warn('已關(guān)閉其他視頻')
            })
            .catch((e) => {
              console.log('close error', e)
            })
        )

        // Use Promise.all to wait for all promises to resolve
        Promise.all(closePromises)
          .then(() => {
            // All videos closed successfully
            console.log('All videos closed successfully')
          })
          .catch((error) => {
            // Handle errors if any of the requests fail
            console.log('Error closing videos:', error)
          })
      }
    }
  },
  computed: {
    cellClass() {
      return function (index) {
        switch (this.cellCount) {
          case 1:
            return ['cell-player-1']
          case 4:
            return ['cell-player-4']
          case 6:
            if (index == 1) return ['cell-player-6-1']
            if (index == 2) return ['cell-player-6-2']
            if (index == 3) return ['cell-player-6-none']
            return ['cell-player-6']
          case 9:
            return ['cell-player-9']
          case 16:
            return ['cell-player-16']
          default:
            break
        }
      }
    }
  }
}
</script>
4. 樣式, 這里有些ant D穿透樣式, 可以去掉:
<style lang="less" scoped>
.header {
  background-color: #034d94;
  padding: 10px 25px;
  border-radius: 10px;
}
.main-body {
  width: 100%;
  height: 90%;
  display: flex;

  .right {
    width: 100%;
    height: 100%;
    .cell {
      margin-top: 0.5%;
      display: flex;
      flex-direction: column;
      height: 100%;
    }
  }
}
.bk-button-group .active {
  background-color: skyblue;
  color: #fff;
  /* Add any other styles for the active button */
}
.cell-tool {
  height: 40px;
  line-height: 40px;
  margin-top: -1px;
  // padding: 0 7px;
}
.cell-player {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  width: 100%;
  height: 100%;
}
.cell-player-4 {
  width: 50%;
  height: 50% !important;
  box-sizing: border-box;
}
.cell-player-1 {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
.cell-player-6-1 {
  width: 66.66%;
  height: 66.66% !important;
  box-sizing: border-box;
}
.cell-player-6-2 {
  width: 33.33%;
  height: 66.66% !important;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}
.cell-player-6-none {
  display: none;
}
.cell-player-6-2-cell {
  width: 100%;
  height: 50% !important;
  box-sizing: border-box;
}
.cell-player-6 {
  width: 33.33%;
  height: 33.33% !important;
  box-sizing: border-box;
}
.cell-player-9 {
  width: 33.33%;
  height: 33.33% !important;
  box-sizing: border-box;
}
.cell-player-16 {
  width: 25%;
  height: 25% !important;
  box-sizing: border-box;
}

.ant-select {
  width: 180px;
}
/deep/.ant-time-picker-input {
  background-color: #034d94;
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff;
  &::placeholder {
    color: #bfbfb5;
  }
}
/deep/ .ant-select-selection--single {
  background-color: #034d94;
  border: 1px solid rgba(255, 255, 255, 0.4);
  color: #fff;
  &::placeholder {
    color: #bfbfb5;
  }
}
/deep/ .ant-select-arrow {
  color: white;
}
/deep/.page-search-none {
  padding: 0;
}
/deep/.ant-svg {
  color: #fff;
}
/deep/.ant-time-picker-icon .ant-time-picker-clock-icon,
.ant-time-picker-clear .ant-time-picker-clock-icon {
  color: #fff;
}
li.ant-select-tree-treenode-disabled > span:not(.ant-select-tree-switcher),
li.ant-select-tree-treenode-disabled > .ant-select-tree-node-content-wrapper,
li.ant-select-tree-treenode-disabled > .ant-select-tree-node-content-wrapper span {
  color: red !important;
}
</style>

到了這里,關(guān)于Vue實(shí)現(xiàn)攝像頭視頻分屏, 使用flv.js接收rtmp/flv視頻流的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • VUE+Django實(shí)現(xiàn)前端開啟攝像頭錄制存儲(chǔ)視頻并直接上傳后端

    VUE+Django實(shí)現(xiàn)前端開啟攝像頭錄制存儲(chǔ)視頻并直接上傳后端

    1.錄制前 2.錄制中 3.錄制結(jié)束下載文件至本地 4.視頻文件同時(shí)上傳至后端接口 參考博客https://blog.csdn.net/wuchenlhy/article/details/79311234?spm=1001.2014.3001.5506 博主在后端這塊寫的十分簡潔明了,可以直接參考實(shí)現(xiàn)開設(shè)后端簡單文件上傳接口的方法 參考文章: https://blog.csdn.net/XH_jing/a

    2024年02月14日
    瀏覽(99)
  • 使用手機(jī)攝像頭實(shí)現(xiàn)視頻監(jiān)控實(shí)時(shí)播放

    視頻監(jiān)控實(shí)時(shí)播放的原理與目前較為流行的直播是一致的,所以采用直播的架構(gòu)實(shí)現(xiàn)視頻監(jiān)控實(shí)時(shí)播放,流程圖如下: 目前實(shí)時(shí)視頻流的傳輸協(xié)議有以下幾種:RTSP、RTMP、HLS、Http-flv。 安卓APP開發(fā)使用HBuilder,而HBuilder內(nèi)置了LivePusher直播推流控件,該控件使用了RTMP協(xié)議,所以

    2023年04月08日
    瀏覽(27)
  • vue2使用rtsp視頻流接入海康威視攝像頭(純前端)

    vue2使用rtsp視頻流接入??低晹z像頭(純前端)

    海康威視官方的RTSP最新取流格式如下: rtsp://用戶名:密碼@IP:554/Streaming/Channels/101 用戶名和密碼 IP就是登陸攝像頭時(shí)候的IP(筆者這里IP是192.168.1.210) 所以筆者的rtsp流地址就是 rtsp://用戶名:密碼@192.168.1.210:554/Streaming/Channels/101 1.1關(guān)閉 螢石云的接入 1.2 調(diào)整視頻編碼為H.264 在此下載

    2024年04月26日
    瀏覽(25)
  • 使用 MFC 和 OpenCV 實(shí)現(xiàn)實(shí)時(shí)攝像頭視頻顯示

    1、引言 MFC 是一個(gè)在 Windows 平臺(tái)上編寫 C++ 應(yīng)用程序的庫,提供了豐富的用戶界面功能。OpenCV(Open Source Computer Vision Library)是一個(gè)開源的計(jì)算機(jī)視覺庫,包含了豐富的圖像處理和計(jì)算機(jī)視覺功能。本文將向大家展示如何將這兩個(gè)庫結(jié)合起來,實(shí)現(xiàn)一個(gè)實(shí)時(shí)顯示攝像頭畫面的簡

    2024年02月13日
    瀏覽(113)
  • LiveGBS流媒體平臺(tái)GB/T28181功能-如何獲取接入的??荡笕A宇視華為攝像頭硬件NVR設(shè)備通道視頻直播流地址HLS/HTTP-FLV/WS-FLV/WebRTC/RTMP/RTSP

    LiveGBS流媒體平臺(tái)GB/T28181功能-如何獲取接入的??荡笕A宇視華為攝像頭硬件NVR設(shè)備通道視頻直播流地址HLS/HTTP-FLV/WS-FLV/WebRTC/RTMP/RTSP

    LiveGBS國標(biāo)GB/T28181流媒體服務(wù)器軟件,支持設(shè)備|平臺(tái)GB28181注冊接入、向上級(jí)聯(lián)第三方國標(biāo)平臺(tái), 可視化的WEB頁面管理(頁面源碼開源);支持云臺(tái)控制、設(shè)備錄像檢索、回放,支持語音對講,用戶管理, 多種協(xié)議流輸出,實(shí)現(xiàn)瀏覽器無插件直播。 在項(xiàng)目過程中,需要播放視頻

    2024年03月25日
    瀏覽(32)
  • JAVACV 讀取攝像頭流將rtsp轉(zhuǎn)flv 通過http-flv和flv.js播放 無插件 純代碼

    1、pom ?2、攝像頭類 3、服務(wù)實(shí)現(xiàn) ?4、拉流轉(zhuǎn)碼 5、前端(vue) 安裝flv.js?? npm install --save flv.js

    2024年02月12日
    瀏覽(28)
  • 吸煙檢測從零開始使用YOLOv5+PyQt5+OpenCV實(shí)現(xiàn)(支持圖片、視頻、攝像頭實(shí)時(shí)檢測)

    吸煙檢測從零開始使用YOLOv5+PyQt5+OpenCV實(shí)現(xiàn)(支持圖片、視頻、攝像頭實(shí)時(shí)檢測)

    全流程 教程,從數(shù)據(jù)采集到模型使用到最終展示。若有任何疑問和建議歡迎評(píng)論區(qū)討論。 先放上最終實(shí)現(xiàn)效果 檢測效果 由上圖我們可以看到,使用YOLOV5完成了吸煙的目標(biāo)識(shí)別檢測,可以達(dá)到mAP可達(dá)85.38%。通過對吸煙的自動(dòng)檢測可以方便商場、醫(yī)院、療養(yǎng)院等公共場合進(jìn)行禁

    2024年02月09日
    瀏覽(25)
  • 大華攝像頭實(shí)時(shí)預(yù)覽(spring boot+websocket+flv.js)Java開發(fā)

    大華攝像頭實(shí)時(shí)預(yù)覽(spring boot+websocket+flv.js)Java開發(fā)

    1.大華NetSDK_JAVA; 這里使用的是 Linux64的架包 2.websocket 前端使用的vue框架? ? 3.flv.js的播放插件? ?? 4.大華攝像頭提供的平臺(tái)(后面稱為官方平臺(tái)) 根據(jù)大華《NetSDK_JAVA編程指導(dǎo)手冊》的流程圖 根據(jù)圖可以得知關(guān)鍵流程為: 初始化sdk——登錄設(shè)備——打開實(shí)時(shí)預(yù)覽——設(shè)置視

    2024年02月04日
    瀏覽(28)
  • OpenCV(視頻加載與攝像頭使用)

    OpenCV(視頻加載與攝像頭使用)

    目錄 1、VideoCapture類 2、視頻屬性get()? 3、視屏文件保存

    2024年02月12日
    瀏覽(24)
  • vue2 對接 ??禂z像頭插件 (視頻WEB插件 V1.5.2)

    vue2 對接 ??禂z像頭插件 (視頻WEB插件 V1.5.2)

    前言 ??狄曨l插件v.1.5.2版本運(yùn)行環(huán)境需要安裝插件VideoWebPlugin.exe,對瀏覽器也有兼容性要求,具體看官方文檔 對應(yīng)下載插件 去??倒倬W(wǎng)下載插件 里面有dome等其他需要用到的 地址: 安裝插件 打開下載的文件里的bin文件 安裝一下VideoWebPlugin vue腳手架中集成插件 把官方資源

    2024年02月03日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包