mirror of
https://github.com/gen2brain/cam2ip.git
synced 2025-12-16 12:28:35 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9d77f03e7 | ||
|
|
37b19fcfe8 | ||
|
|
5006c48690 | ||
|
|
d340fa2dc3 | ||
|
|
fa5233255e | ||
|
|
ac555cbf7b | ||
|
|
e1f03b55a1 | ||
|
|
3c0c949f31 | ||
|
|
8a740337ab |
16
README.md
16
README.md
@@ -11,17 +11,19 @@ or
|
|||||||
|
|
||||||
### Requirements
|
### Requirements
|
||||||
|
|
||||||
* [OpenCV 2.x](http://opencv.org/)
|
* [OpenCV](http://opencv.org/) (default is version 2.x via [go-opencv](https://github.com/lazywei/go-opencv), use `-tags cv3` for [gocv](https://github.com/hybridgroup/gocv))
|
||||||
|
* [libjpeg-turbo](https://www.libjpeg-turbo.org/) (use `-tags jpeg` for native image/jpeg, but note that CPU usage will be much higher)
|
||||||
|
|
||||||
|
|
||||||
### Download
|
### Download
|
||||||
|
|
||||||
Binaries are compiled with static OpenCV library:
|
Binaries are compiled with static OpenCV/libjpeg-turbo libraries, they should just work:
|
||||||
|
|
||||||
- [Linux 64bit](https://github.com/gen2brain/cam2ip/releases/download/1.3/cam2ip-1.3-64bit.tar.gz)
|
- [Linux 64bit](https://github.com/gen2brain/cam2ip/releases/download/1.4/cam2ip-1.4-64bit.tar.gz)
|
||||||
- [RPi 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.3/cam2ip-1.3-RPi.tar.gz)
|
- [RPi 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.4/cam2ip-1.4-RPi.tar.gz)
|
||||||
- [RPi3 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.3/cam2ip-1.3-RPi3.tar.gz)
|
- [RPi3 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.4/cam2ip-1.4-RPi3.tar.gz)
|
||||||
- [Windows 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.3/cam2ip-1.3.zip)
|
- [Windows 32bit](https://github.com/gen2brain/cam2ip/releases/download/1.4/cam2ip-1.4.zip)
|
||||||
|
- [Windows 64bit](https://github.com/gen2brain/cam2ip/releases/download/1.4/cam2ip-1.4-64bit.zip)
|
||||||
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
@@ -48,6 +50,8 @@ Usage of ./cam2ip:
|
|||||||
Camera index
|
Camera index
|
||||||
-nowebgl
|
-nowebgl
|
||||||
Disable WebGL drawing of images (html handler)
|
Disable WebGL drawing of images (html handler)
|
||||||
|
-rotate int
|
||||||
|
Rotate image, valid values are 90, 180, 270
|
||||||
-video-file string
|
-video-file string
|
||||||
Use video file instead of camera
|
Use video file instead of camera
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
name = "cam2ip"
|
name = "cam2ip"
|
||||||
version = "1.3"
|
version = "1.4"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -22,6 +22,7 @@ func main() {
|
|||||||
flag.IntVar(&srv.Delay, "delay", 10, "Delay between frames, in milliseconds")
|
flag.IntVar(&srv.Delay, "delay", 10, "Delay between frames, in milliseconds")
|
||||||
flag.Float64Var(&srv.FrameWidth, "width", 640, "Frame width")
|
flag.Float64Var(&srv.FrameWidth, "width", 640, "Frame width")
|
||||||
flag.Float64Var(&srv.FrameHeight, "height", 480, "Frame height")
|
flag.Float64Var(&srv.FrameHeight, "height", 480, "Frame height")
|
||||||
|
flag.IntVar(&srv.Rotate, "rotate", 0, "Rotate image, valid values are 90, 180, 270")
|
||||||
flag.BoolVar(&srv.NoWebGL, "nowebgl", false, "Disable WebGL drawing of images (html handler)")
|
flag.BoolVar(&srv.NoWebGL, "nowebgl", false, "Disable WebGL drawing of images (html handler)")
|
||||||
flag.StringVar(&srv.Bind, "bind-addr", ":56000", "Bind address")
|
flag.StringVar(&srv.Bind, "bind-addr", ":56000", "Bind address")
|
||||||
flag.StringVar(&srv.Htpasswd, "htpasswd-file", "", "Path to htpasswd file, if empty auth is disabled")
|
flag.StringVar(&srv.Htpasswd, "htpasswd-file", "", "Path to htpasswd file, if empty auth is disabled")
|
||||||
@@ -48,7 +49,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if srv.FileName != "" {
|
if srv.FileName != "" {
|
||||||
vid, err := video.New(srv.FileName)
|
vid, err := video.New(video.Options{srv.FileName, srv.Rotate})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@@ -56,7 +57,7 @@ func main() {
|
|||||||
|
|
||||||
srv.Reader = vid
|
srv.Reader = vid
|
||||||
} else {
|
} else {
|
||||||
cam, err := camera.New(srv.Index)
|
cam, err := camera.New(camera.Options{srv.Index, srv.Rotate})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// +build !cv3
|
||||||
|
|
||||||
// Package camera.
|
// Package camera.
|
||||||
package camera
|
package camera
|
||||||
|
|
||||||
@@ -5,64 +7,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
"github.com/lazywei/go-opencv/opencv"
|
"github.com/lazywei/go-opencv/opencv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Property identifiers.
|
// Options.
|
||||||
const (
|
type Options struct {
|
||||||
PropPosMsec = iota
|
Index int
|
||||||
PropPosFrames
|
Rotate int
|
||||||
PropPosAviRatio
|
}
|
||||||
PropFrameWidth
|
|
||||||
PropFrameHeight
|
|
||||||
PropFps
|
|
||||||
PropFourcc
|
|
||||||
PropFrameCount
|
|
||||||
PropFormat
|
|
||||||
PropMode
|
|
||||||
PropBrightness
|
|
||||||
PropContrast
|
|
||||||
PropSaturation
|
|
||||||
PropHue
|
|
||||||
PropGain
|
|
||||||
PropExposure
|
|
||||||
PropConvertRgb
|
|
||||||
PropWhiteBalanceU
|
|
||||||
PropRectification
|
|
||||||
PropMonocrome
|
|
||||||
PropSharpness
|
|
||||||
PropAutoExposure
|
|
||||||
PropGamma
|
|
||||||
PropTemperature
|
|
||||||
PropTrigger
|
|
||||||
PropTriggerDelay
|
|
||||||
PropWhiteBalanceV
|
|
||||||
PropZoom
|
|
||||||
PropFocus
|
|
||||||
PropGuid
|
|
||||||
PropIsoSpeed
|
|
||||||
PropMaxDc1394
|
|
||||||
PropBacklight
|
|
||||||
PropPan
|
|
||||||
PropTilt
|
|
||||||
PropRoll
|
|
||||||
PropIris
|
|
||||||
PropSettings
|
|
||||||
PropBuffersize
|
|
||||||
)
|
|
||||||
|
|
||||||
// Camera represents camera.
|
// Camera represents camera.
|
||||||
type Camera struct {
|
type Camera struct {
|
||||||
|
opts Options
|
||||||
camera *opencv.Capture
|
camera *opencv.Capture
|
||||||
|
frame *opencv.IplImage
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns new Camera for given camera index.
|
// New returns new Camera for given camera index.
|
||||||
func New(index int) (camera *Camera, err error) {
|
func New(opts Options) (camera *Camera, err error) {
|
||||||
camera = &Camera{}
|
camera = &Camera{}
|
||||||
|
camera.opts = opts
|
||||||
|
|
||||||
camera.camera = opencv.NewCameraCapture(index)
|
camera.camera = opencv.NewCameraCapture(opts.Index)
|
||||||
if camera.camera == nil {
|
if camera.camera == nil {
|
||||||
err = fmt.Errorf("camera: can not open camera %d", index)
|
err = fmt.Errorf("camera: can not open camera %d", opts.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -71,8 +40,26 @@ func New(index int) (camera *Camera, err error) {
|
|||||||
// Read reads next frame from camera and returns image.
|
// Read reads next frame from camera and returns image.
|
||||||
func (c *Camera) Read() (img image.Image, err error) {
|
func (c *Camera) Read() (img image.Image, err error) {
|
||||||
if c.camera.GrabFrame() {
|
if c.camera.GrabFrame() {
|
||||||
frame := c.camera.RetrieveFrame(1)
|
c.frame = c.camera.RetrieveFrame(1)
|
||||||
img = frame.ToImage()
|
|
||||||
|
if c.frame == nil {
|
||||||
|
err = fmt.Errorf("camera: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img = c.frame.ToImage()
|
||||||
|
if c.opts.Rotate == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.opts.Rotate {
|
||||||
|
case 90:
|
||||||
|
img = imaging.Rotate90(img)
|
||||||
|
case 180:
|
||||||
|
img = imaging.Rotate180(img)
|
||||||
|
case 270:
|
||||||
|
img = imaging.Rotate270(img)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("camera: can not grab frame")
|
err = fmt.Errorf("camera: can not grab frame")
|
||||||
}
|
}
|
||||||
@@ -86,8 +73,8 @@ func (c *Camera) GetProperty(id int) float64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetProperty sets a camera property.
|
// SetProperty sets a camera property.
|
||||||
func (c *Camera) SetProperty(id int, value float64) int {
|
func (c *Camera) SetProperty(id int, value float64) {
|
||||||
return c.camera.SetProperty(id, value)
|
c.camera.SetProperty(id, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes camera.
|
// Close closes camera.
|
||||||
@@ -97,6 +84,7 @@ func (c *Camera) Close() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.frame.Release()
|
||||||
c.camera.Release()
|
c.camera.Release()
|
||||||
c.camera = nil
|
c.camera = nil
|
||||||
return
|
return
|
||||||
|
|||||||
44
camera/camera_const.go
Normal file
44
camera/camera_const.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package camera
|
||||||
|
|
||||||
|
// Property identifiers.
|
||||||
|
const (
|
||||||
|
PropPosMsec = iota
|
||||||
|
PropPosFrames
|
||||||
|
PropPosAviRatio
|
||||||
|
PropFrameWidth
|
||||||
|
PropFrameHeight
|
||||||
|
PropFps
|
||||||
|
PropFourcc
|
||||||
|
PropFrameCount
|
||||||
|
PropFormat
|
||||||
|
PropMode
|
||||||
|
PropBrightness
|
||||||
|
PropContrast
|
||||||
|
PropSaturation
|
||||||
|
PropHue
|
||||||
|
PropGain
|
||||||
|
PropExposure
|
||||||
|
PropConvertRgb
|
||||||
|
PropWhiteBalanceU
|
||||||
|
PropRectification
|
||||||
|
PropMonocrome
|
||||||
|
PropSharpness
|
||||||
|
PropAutoExposure
|
||||||
|
PropGamma
|
||||||
|
PropTemperature
|
||||||
|
PropTrigger
|
||||||
|
PropTriggerDelay
|
||||||
|
PropWhiteBalanceV
|
||||||
|
PropZoom
|
||||||
|
PropFocus
|
||||||
|
PropGuid
|
||||||
|
PropIsoSpeed
|
||||||
|
PropMaxDc1394
|
||||||
|
PropBacklight
|
||||||
|
PropPan
|
||||||
|
PropTilt
|
||||||
|
PropRoll
|
||||||
|
PropIris
|
||||||
|
PropSettings
|
||||||
|
PropBuffersize
|
||||||
|
)
|
||||||
99
camera/camera_cv3.go
Normal file
99
camera/camera_cv3.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// +build cv3
|
||||||
|
|
||||||
|
// Package camera.
|
||||||
|
package camera
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"gocv.io/x/gocv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options.
|
||||||
|
type Options struct {
|
||||||
|
Index int
|
||||||
|
Rotate int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Camera represents camera.
|
||||||
|
type Camera struct {
|
||||||
|
opts Options
|
||||||
|
camera *gocv.VideoCapture
|
||||||
|
frame *gocv.Mat
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns new Camera for given camera index.
|
||||||
|
func New(opts Options) (camera *Camera, err error) {
|
||||||
|
camera = &Camera{}
|
||||||
|
camera.opts = opts
|
||||||
|
|
||||||
|
mat := gocv.NewMat()
|
||||||
|
camera.frame = &mat
|
||||||
|
|
||||||
|
camera.camera, err = gocv.VideoCaptureDevice(opts.Index)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("camera: can not open camera %d: %s", opts.Index, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads next frame from camera and returns image.
|
||||||
|
func (c *Camera) Read() (img image.Image, err error) {
|
||||||
|
ok := c.camera.Read(c.frame)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("camera: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img, e := c.frame.ToImage()
|
||||||
|
if e != nil {
|
||||||
|
err = fmt.Errorf("camera: %v", e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.frame == nil {
|
||||||
|
err = fmt.Errorf("camera: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.opts.Rotate == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch c.opts.Rotate {
|
||||||
|
case 90:
|
||||||
|
img = imaging.Rotate90(img)
|
||||||
|
case 180:
|
||||||
|
img = imaging.Rotate180(img)
|
||||||
|
case 270:
|
||||||
|
img = imaging.Rotate270(img)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProperty returns the specified camera property.
|
||||||
|
func (c *Camera) GetProperty(id int) float64 {
|
||||||
|
return c.camera.Get(gocv.VideoCaptureProperties(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProperty sets a camera property.
|
||||||
|
func (c *Camera) SetProperty(id int, value float64) {
|
||||||
|
c.camera.Set(gocv.VideoCaptureProperties(id), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes camera.
|
||||||
|
func (c *Camera) Close() (err error) {
|
||||||
|
if c.camera == nil {
|
||||||
|
err = fmt.Errorf("camera: camera is not opened")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.frame.Close()
|
||||||
|
err = c.camera.Close()
|
||||||
|
c.camera = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
|
// +build !jpeg
|
||||||
|
|
||||||
// Package encoder.
|
// Package encoder.
|
||||||
package encoder
|
package encoder
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
//"image/jpeg"
|
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
jpeg "github.com/antonini/golibjpegturbo"
|
jpeg "github.com/antonini/golibjpegturbo"
|
||||||
|
|||||||
30
encoder/encode_jpeg.go
Normal file
30
encoder/encode_jpeg.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
// +build jpeg
|
||||||
|
|
||||||
|
// Package encoder.
|
||||||
|
package encoder
|
||||||
|
|
||||||
|
import (
|
||||||
|
"image"
|
||||||
|
"image/jpeg"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New returns a new Encoder.
|
||||||
|
func New(w io.Writer) *Encoder {
|
||||||
|
return &Encoder{w}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encoder struct.
|
||||||
|
type Encoder struct {
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encode encodes image to JPEG.
|
||||||
|
func (e Encoder) Encode(img image.Image) error {
|
||||||
|
err := jpeg.Encode(e.w, img, &jpeg.Options{Quality: 75})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
11
make.bash
11
make.bash
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
CHROOT="/usr/x86_64-pc-linux-gnu-static"
|
CHROOT="/usr/x86_64-pc-linux-gnu-static"
|
||||||
MINGW="/usr/i686-w64-mingw32"
|
MINGW="/usr/i686-w64-mingw32"
|
||||||
|
MINGW64="/usr/x86_64-w64-mingw32"
|
||||||
RPI="/usr/armv6j-hardfloat-linux-gnueabi"
|
RPI="/usr/armv6j-hardfloat-linux-gnueabi"
|
||||||
RPI3="/usr/armv7a-hardfloat-linux-gnueabi"
|
RPI3="/usr/armv7a-hardfloat-linux-gnueabi"
|
||||||
|
|
||||||
@@ -11,9 +12,9 @@ LIBRARY_PATH="$CHROOT/usr/lib:$CHROOT/lib" \
|
|||||||
PKG_CONFIG_PATH="$CHROOT/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$CHROOT/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$CHROOT/usr/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$CHROOT/usr/lib/pkgconfig" \
|
||||||
CGO_LDFLAGS="-L$CHROOT/usr/lib -L$CHROOT/lib" \
|
CGO_LDFLAGS="-L$CHROOT/usr/lib -L$CHROOT/lib" \
|
||||||
|
CGO_CFLAGS="-I$CHROOT/usr/include" \
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -v -x -o build/cam2ip.linux.amd64 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -v -x -o build/cam2ip.linux.amd64 -ldflags "-linkmode external -s -w" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/i686-w64-mingw32-pkg-config" \
|
PKG_CONFIG="/usr/bin/i686-w64-mingw32-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MINGW/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MINGW/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$MINGW/usr/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$MINGW/usr/lib/pkgconfig" \
|
||||||
@@ -22,6 +23,14 @@ CGO_CFLAGS="-I$MINGW/usr/include" \
|
|||||||
CC="i686-w64-mingw32-gcc" CXX="i686-w64-mingw32-g++" \
|
CC="i686-w64-mingw32-gcc" CXX="i686-w64-mingw32-g++" \
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -v -x -o build/cam2ip.exe -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -v -x -o build/cam2ip.exe -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
|
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$MINGW64/usr/lib/pkgconfig" \
|
||||||
|
PKG_CONFIG_LIBDIR="$MINGW64/usr/lib/pkgconfig" \
|
||||||
|
CGO_LDFLAGS="-L$MINGW64/usr/lib" \
|
||||||
|
CGO_CFLAGS="-I$MINGW64/usr/include" \
|
||||||
|
CC="x86_64-w64-mingw32-gcc" CXX="x86_64-w64-mingw32-g++" \
|
||||||
|
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -v -x -o build/cam2ip.exe.amd64 -ldflags "-linkmode external -s -w '-extldflags=-static'" github.com/gen2brain/cam2ip
|
||||||
|
|
||||||
PKG_CONFIG="/usr/bin/armv6j-hardfloat-linux-gnueabi-pkg-config" \
|
PKG_CONFIG="/usr/bin/armv6j-hardfloat-linux-gnueabi-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$RPI/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$RPI/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$RPI/usr/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$RPI/usr/lib/pkgconfig" \
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ type Server struct {
|
|||||||
FrameWidth float64
|
FrameWidth float64
|
||||||
FrameHeight float64
|
FrameHeight float64
|
||||||
|
|
||||||
|
Rotate int
|
||||||
|
|
||||||
NoWebGL bool
|
NoWebGL bool
|
||||||
|
|
||||||
FileName string
|
FileName string
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// +build !cv3
|
||||||
|
|
||||||
// Package video.
|
// Package video.
|
||||||
package video
|
package video
|
||||||
|
|
||||||
@@ -5,21 +7,31 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
"github.com/lazywei/go-opencv/opencv"
|
"github.com/lazywei/go-opencv/opencv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Options.
|
||||||
|
type Options struct {
|
||||||
|
Filename string
|
||||||
|
Rotate int
|
||||||
|
}
|
||||||
|
|
||||||
// Video represents video.
|
// Video represents video.
|
||||||
type Video struct {
|
type Video struct {
|
||||||
|
opts Options
|
||||||
video *opencv.Capture
|
video *opencv.Capture
|
||||||
|
frame *opencv.IplImage
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns new Video for given path.
|
// New returns new Video for given path.
|
||||||
func New(filename string) (video *Video, err error) {
|
func New(opts Options) (video *Video, err error) {
|
||||||
video = &Video{}
|
video = &Video{}
|
||||||
|
video.opts = opts
|
||||||
|
|
||||||
video.video = opencv.NewFileCapture(filename)
|
video.video = opencv.NewFileCapture(opts.Filename)
|
||||||
if video.video == nil {
|
if video.video == nil {
|
||||||
err = fmt.Errorf("video: can not open video %s", filename)
|
err = fmt.Errorf("video: can not open video %s", opts.Filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -28,8 +40,25 @@ func New(filename string) (video *Video, err error) {
|
|||||||
// Read reads next frame from video and returns image.
|
// Read reads next frame from video and returns image.
|
||||||
func (v *Video) Read() (img image.Image, err error) {
|
func (v *Video) Read() (img image.Image, err error) {
|
||||||
if v.video.GrabFrame() {
|
if v.video.GrabFrame() {
|
||||||
frame := v.video.RetrieveFrame(1)
|
v.frame = v.video.RetrieveFrame(1)
|
||||||
img = frame.ToImage()
|
if v.frame == nil {
|
||||||
|
err = fmt.Errorf("video: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img = v.frame.ToImage()
|
||||||
|
if v.opts.Rotate == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.opts.Rotate {
|
||||||
|
case 90:
|
||||||
|
img = imaging.Rotate90(img)
|
||||||
|
case 180:
|
||||||
|
img = imaging.Rotate180(img)
|
||||||
|
case 270:
|
||||||
|
img = imaging.Rotate270(img)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("video: can not grab frame")
|
err = fmt.Errorf("video: can not grab frame")
|
||||||
}
|
}
|
||||||
@@ -44,6 +73,7 @@ func (v *Video) Close() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.frame.Release()
|
||||||
v.video.Release()
|
v.video.Release()
|
||||||
v.video = nil
|
v.video = nil
|
||||||
return
|
return
|
||||||
|
|||||||
89
video/video_cv3.go
Normal file
89
video/video_cv3.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
// +build cv3
|
||||||
|
|
||||||
|
// Package video.
|
||||||
|
package video
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
|
||||||
|
"github.com/disintegration/imaging"
|
||||||
|
"gocv.io/x/gocv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Options.
|
||||||
|
type Options struct {
|
||||||
|
Filename string
|
||||||
|
Rotate int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Video represents video.
|
||||||
|
type Video struct {
|
||||||
|
opts Options
|
||||||
|
video *gocv.VideoCapture
|
||||||
|
frame *gocv.Mat
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns new Video for given path.
|
||||||
|
func New(opts Options) (video *Video, err error) {
|
||||||
|
video = &Video{}
|
||||||
|
video.opts = opts
|
||||||
|
|
||||||
|
mat := gocv.NewMat()
|
||||||
|
video.frame = &mat
|
||||||
|
|
||||||
|
video.video, err = gocv.VideoCaptureFile(opts.Filename)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("video: can not open video %s: %s", opts.Filename, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read reads next frame from video and returns image.
|
||||||
|
func (v *Video) Read() (img image.Image, err error) {
|
||||||
|
ok := v.video.Read(v.frame)
|
||||||
|
if !ok {
|
||||||
|
err = fmt.Errorf("video: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.frame == nil {
|
||||||
|
err = fmt.Errorf("video: can not grab frame")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
img, e := v.frame.ToImage()
|
||||||
|
if e != nil {
|
||||||
|
err = fmt.Errorf("video: %v", e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if v.opts.Rotate == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.opts.Rotate {
|
||||||
|
case 90:
|
||||||
|
img = imaging.Rotate90(img)
|
||||||
|
case 180:
|
||||||
|
img = imaging.Rotate180(img)
|
||||||
|
case 270:
|
||||||
|
img = imaging.Rotate270(img)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes video.
|
||||||
|
func (v *Video) Close() (err error) {
|
||||||
|
if v.video == nil {
|
||||||
|
err = fmt.Errorf("video: video is not opened")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v.frame.Close()
|
||||||
|
err = v.video.Close()
|
||||||
|
v.video = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user