go用opencv实现图像清晰度识别

1. 安装opencv

linux: Linux :: GoCV - Golang Computer Vision Using OpenCV 4

mac: https://gocv.io/getting-started/macos/

windows:Windows :: GoCV - Golang Computer Vision Using OpenCV 4

dockerfile:

FROM ubuntu:latest as build-stage

ENV OPENCV_VERSION=4.4.0
ENV BUILD="ca-certificates \
    autoconf \
    libgtk2.0-dev \
    libavcodec-dev \
    libavformat-dev \
    libswscale-dev \
    libtbb2 \
    libtbb-dev \
    libjpeg-dev \
    libpng-dev \
    libtiff-dev \
    libdc1394-22-dev \
    automake \
    git \
    musl-dev \
    cmake \
    clang \
    make \
    gcc \
    g++ \
    libc-dev \
    libwebp-dev \
    unzip \
    tzdata \
    python3-dev "

ENV DEV="clang  cmake pkgconf \
         libgphoto2-dev libpng-dev \
         libavc1394-dev"

RUN export DEBIAN_FRONTEND=noninteractive && \
    apt-get update -y && \
    apt-get install -y  ${BUILD} ${DEV} \
    && ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && dpkg-reconfigure --frontend noninteractive tzdata \
    && apt-get install -y wget

RUN mkdir /tmp/opencv && \
    cd /tmp/opencv && \
    wget -O opencv.tar.gz https://github.91chifun.workers.dev//https://github.com/opencv/opencv/archive/${OPENCV_VERSION}.tar.gz && \
    wget -O opencv_contrib.tar.gz https://github.91chifun.workers.dev//https://github.com/opencv/opencv_contrib/archive/${OPENCV_VERSION}.tar.gz
RUN cd /tmp/opencv &&  \
    tar -zxvf opencv.tar.gz
RUN cd /tmp/opencv &&    tar -zxvf opencv_contrib.tar.gz

COPY boostdesc* /tmp/opencv/opencv_contrib-${OPENCV_VERSION}/modules/xfeatures2d/src/
COPY vgg* /tmp/opencv/opencv_contrib-${OPENCV_VERSION}/modules/xfeatures2d/src/
RUN cd /tmp/opencv/opencv_contrib-${OPENCV_VERSION}/modules/xfeatures2d/src/ && ls

RUN cd /tmp/opencv && \
    mkdir /tmp/opencv/opencv-${OPENCV_VERSION}/build && cd /tmp/opencv/opencv-${OPENCV_VERSION}/build && \
    cmake \
    -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=/tmp/opencv/opencv_contrib-${OPENCV_VERSION}/modules \
    -D BUILD_DOCS=OFF \
    -D BUILD_SHARED_LIBS=ON \
    -D BUILD_opencv_freetype=ON \
    -D BUILD_EXAMPLES=OFF \
    -D BUILD_TESTS=OFF \
    -D BUILD_PERF_TESTS=OFF \
    -D BUILD_opencv_java=NO \
    -D BUILD_opencv_python=NO \
    -D BUILD_opencv_python2=NO \
    -D BUILD_opencv_python3=NO \
    -D WITH_JASPER=OFF -DOPENCV_GENERATE_PKGCONFIG=ON ..&& \
    make -j4 && \
    make install && \
    cd && rm -rf /tmp/opencv


#RUN  apt-get -y remove ${BUILD} ${DEV} && \
#    rm -rf /var/cache/apk/*

ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
ENV LD_LIBRARY_PATH /usr/local/lib
ENV CGO_CPPFLAGS -I/usr/local/include
ENV CGO_CXXFLAGS "--std=c++1z"
ENV CGO_LDFLAGS "-L/usr/local/lib -lopencv_core -lopencv_face -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_dnn -lopencv_xfeatures2d -lopencv_plot -lopencv_tracking"
RUN ls /usr/local/lib
FROM ubuntu:latest

COPY --from=build-stage /usr/local/lib /usr/local/lib
COPY --from=build-stage /usr/local/lib/pkgconfig/opencv4.pc /usr/local/lib/pkgconfig/opencv4.pc
COPY --from=build-stage /usr/local/include/opencv4/opencv2 /usr/local/include/opencv4/opencv2
COPY --from=build-stage /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu

COPY --from=build-stage /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2
COPY --from=build-stage /usr/lib64/ld-linux-x86-64.so.2 /usr/lib64/ld-linux-x86-64.so.2


#RUN export DEBIAN_FRONTEND=noninteractive && \
#    apt-get update -y && \
#    apt-get install -y libglib2.0-dev libgtk2.0-dev libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev \
#    && ln -fs /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
#    && dpkg-reconfigure --frontend noninteractive tzdata

WORKDIR /bin
COPY . /bin
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
ENV LD_LIBRARY_PATH /usr/local/lib
ENV CGO_CPPFLAGS -I/usr/local/include
ENV GODEBUG "madvdontneed=1"
ENV CGO_CXXFLAGS "--std=c++1z"
ENV CGO_LDFLAGS "-L/usr/local/lib -lopencv_core -lopencv_face -lopencv_videoio -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs -lopencv_objdetect -lopencv_features2d -lopencv_video -lopencv_dnn -lopencv_xfeatures2d -lopencv_plot -lopencv_tracking"
EXPOSE 5005
RUN echo "/usr/local/lib" >> /etc/ld.so.conf.d/opencv.conf
RUN ldconfig
RUN chmod +x main
#RUN echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig" > /etc/bash.bashrc
#RUN echo "export PKG_CONFIG_PATH" >> /etc/bash.bashrc
#RUN source /etc/bash.bashrc
#RUN sudo updatedb

CMD ["./main"]

docker golang我是编译好执行文件在copy 进去的 里面其实就只有opencv 没有golang 。需要golang可以在加一层 这里没加

2.golang代码:

最好是要做限流,加协程池或线程池都是可以的,无线开协程高并发下,不做限制内存会爆。

package goroutine

import "github.com/panjf2000/ants/v2"

var Pool *ants.Pool


import (
    "context"
    "crypto/tls"
    "fmt"
    "image"
    "image/jpeg"
    "image/png"
    "net/http"
    "runtime"
    "rxt/internal/config"
    "rxt/internal/goroutine"
    "sync"
    "time"
)
type ClarityRequest struct {
    Url                  []string `protobuf:"bytes,1,rep,name=url,proto3" json:"url,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}
type ClarityResponse struct {
    Result               []*ClarityImg `protobuf:"bytes,1,rep,name=result,proto3" json:"result,omitempty"`
    XXX_NoUnkeyedLiteral struct{}      `json:"-"`
    XXX_unrecognized     []byte        `json:"-"`
    XXX_sizecache        int32         `json:"-"`
}
type ClarityImg struct {
    Url                  string   `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
    Clarity              int32    `protobuf:"varint,2,opt,name=clarity,proto3" json:"clarity,omitempty"`
    XXX_NoUnkeyedLiteral struct{} `json:"-"`
    XXX_unrecognized     []byte   `json:"-"`
    XXX_sizecache        int32    `json:"-"`
}


func (s Server) Clarity(ctx context.Context, request *student.ClarityRequest) (*student.ClarityResponse, error) {
    var clarityImg []*student.ClarityImg
    var wg sync.WaitGroup
    wg.Add(len(request.Url))
    tr := &http.Transport{ //解决x509: certificate signed by unknown authority
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{
        Timeout:   15 * time.Second,
        Transport: tr, //解决x509: certificate signed by unknown authority
    }
    ch := make(chan string, len(request.Url))
    qiniu := config.New().GetString("qiniuDomainDefault")
    qiniu = "https://" + qiniu + "/"
    for _, url := range request.Url {
        ch <- url
        f := func() {
            url := <-ch
            fmt.Println(url)
            defer wg.Done()
            req, err := http.NewRequest("GET", qiniu+url, nil)
            if err != nil {
                fmt.Println(err.Error())
                return
            }
            res, err := client.Do(req)
            if err != nil {
                clarityImg = append(clarityImg, &student.ClarityImg{
                    Url:     url,
                    Clarity: 2,
                })
                fmt.Println(err)
                return
            }
            defer res.Body.Close()
            contentType := res.Header.Get("content-type")
            var img image.Image
            if contentType == "image/png" {
                img, err = png.Decode(res.Body)
            }
            if contentType == "image/jpeg" {
                img, err = jpeg.Decode(res.Body)
            }

            if err != nil {
                fmt.Println(err)
            }
            if contentType == "image/gif" {
                clarityImg = append(clarityImg, &student.ClarityImg{
                    Url:     url,
                    Clarity: 1,
                })
                return
            }
            if err != nil {
                clarityImg = append(clarityImg, &student.ClarityImg{
                    Url:     url,
                    Clarity: 2,
                })
                return
            }
            if img == nil {
                fmt.Println(img)
                return
            }
            result, err := quality.New().Clarity(img)
            if err != nil {
                clarityImg = append(clarityImg, &student.ClarityImg{
                    Url:     url,
                    Clarity: 2,
                })
                return
            }
            var clarity int32 = 2
            if result {
                clarity = 1
            }
            clarityImg = append(clarityImg, &student.ClarityImg{
                Url:     url,
                Clarity: clarity,
            })
        }
        goroutine.Pool.Submit(f)
    }
    wg.Wait()
    runtime.GC()
    return &student.ClarityResponse{
        Result: clarityImg,
    }, nil
}

import (
    "gocv.io/x/gocv"
    "image"
)
// 清晰度检测
func (c *V1) Clarity(img image.Image) (bool, error) {
    mat, err := gocv.ImageToMatRGB(img)
    if err != nil || mat.Empty() {
        if mat.Empty() == false {
            mat.Close()
        }
        return false, err
    }
    matClone := mat.Clone()
    //如果图片是多通道 就进去转换
    if mat.Channels() != 1 {
        // 将图像转换为灰度显示
        gocv.CvtColor(mat, &matClone, gocv.ColorRGBToGray)
    }
    mat.Close()

    destCanny := gocv.NewMat()

    destCannyC := gocv.NewMat()

    destCannyD := gocv.NewMat()
    //边缘检测 
    gocv.Canny(matClone, &destCanny, 200, 200)
    //求矩阵的均值与标准差
    gocv.MeanStdDev(destCanny, &destCannyC, &destCannyD)
    destCanny.Close()
    destCannyC.Close()
    if destCannyD.GetDoubleAt(0, 0) == 0 {
        destCannyD.Close()
        matClone.Close()
        return false, nil
    }
    destCannyD.Close()

    destC := gocv.NewMat()
    destD := gocv.NewMat()
    destA := gocv.NewMat()
    //Laplace算子
    gocv.Laplacian(matClone, &destA, gocv.MatTypeCV64F, 3, 1, 0, gocv.BorderDefault)
    gocv.MeanStdDev(destA, &destC, &destD)
    destC.Close()
    destA.Close()
    destMean := gocv.NewMat()
    gocv.Laplacian(matClone, &destMean, gocv.MatTypeCV16U, 3, 1, 0, gocv.BorderDefault)
    mean := destMean.Mean()
    destMean.Close()
    matClone.Close()
    if mean.Val1 > 5 || destD.GetDoubleAt(0, 0) > 20 {
        destD.Close()
        return true, nil
    }
    destD.Close()
    return false, nil
}

这里对于后端建议图片先上传到oss存储在验证会好,云计算嘛可以走内网,速度比上传应该是快一点的。
相关阈值需要图片自行测试调整

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 1

兄弟 我这边使用了gocv包mac环境编译生成可自行文件(用于Linux环境); 环境:export CGO_CXXFLAGS="--std=c++11" export CGO_CPPFLAGS="-I/usr/local/Cellar/opencv/4.8.1_5/include" export CGO_LDFLAGS="-L/usr/local/Cellar/opencv/4.8.1_5/lib -lopencv_stitching -lopencv_superres -lopencv_videostab -lopencv_aruco -lopencv_bgsegm -lopencv_bioinspired -lopencv_ccalib -lopencv_dnn_objdetect -lopencv_dpm -lopencv_face -lopencv_photo -lopencv_fuzzy -lopencv_hfs -lopencv_img_hash -lopencv_line_descriptor -lopencv_optflow -lopencv_reg -lopencv_rgbd -lopencv_saliency -lopencv_stereo -lopencv_structured_light -lopencv_phase_unwrapping -lopencv_surface_matching -lopencv_tracking -lopencv_datasets -lopencv_dnn -lopencv_plot -lopencv_xfeatures2d -lopencv_shape -lopencv_video -lopencv_ml -lopencv_ximgproc -lopencv_calib3d -lopencv_features2d -lopencv_highgui -lopencv_videoio -lopencv_flann -lopencv_xobjdetect -lopencv_imgcodecs -lopencv_objdetect -lopencv_xphoto -lopencv_imgproc -lopencv_core"

命令: CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -o videoThumbnail

报错 : # gocv.io/x/gocv /usr/local/Cellar/musl-cross/0.9.9_1/libexec/bin/../lib/gcc/x86_64-linux-musl/9.2.0/../../../../x86_64-linux-musl/bin/ld: $WORK/b046/_x021.o: in function ArucoDetector_New': aruco.cpp:(.text+0x22): undefined reference tocv::aruco::getPredefinedDictionary(cv::aruco::PredefinedDictionaryType)'

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!