首页 > 解决方案 > 将opencv c++代码转换为opencv python代码

问题描述

您好,我有以下 c++ 代码并想将其转换为 python 代码,但是对于 cv2,opencv 函数在 python 中不可用。我怎样才能改变它?我认为这是来自 opencv 的旧功能。这是从视频中删除背景的功能。我正在使用带有 python 的 opencv 版本 4。

#include "stdafx.h"
#include "RunningGaussianAverage.h"

RunningGaussianAverage::RunningGaussianAverage()
{
    learningRate = 5;
    K = 20;
    Imu = ImuNext = NULL;
    Isigma = IsigmaNext = NULL;
}

void RunningGaussianAverage::runningGaussianAverage( CvCapture *capture )
{
    CvSize sz;
    double alpha, k;
    IplImage *frameTemp, *frame, *Itemp1, *Itemp2, *Itemp_StdDeviation, *Itemp3;

    cvNamedWindow("Original");
    cvNamedWindow("Running Gaussian Average");

    cvCreateTrackbar("LearningRate", "Running Gaussian Average", &learningRate, 100, NULL);
    cvCreateTrackbar("K", "Running Gaussian Average", &K, 100, NULL);

    frameTemp = cvQueryFrame(capture);
    sz = cvGetSize(frameTemp);
    Imu = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    ImuNext = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    Isigma = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    IsigmaNext = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    frame = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    Itemp1 = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    Itemp2 = cvCreateImage(sz, IPL_DEPTH_8U, 1);
    Itemp_StdDeviation = cvCreateImage(sz, IPL_DEPTH_32F, 1);
    Itemp3 = cvCreateImage(sz, IPL_DEPTH_32F, 1);

    cvZero(Imu);
    cvZero(ImuNext);
    cvZero(Isigma);
    cvZero(IsigmaNext);

    cvCvtColor(frameTemp, Itemp1, CV_RGB2GRAY);
    frameTemp = cvQueryFrame(capture);
    cvCvtColor(frameTemp, frame, CV_RGB2GRAY);
    cvAbsDiff(frame, Itemp1, Imu);

    cvAdd(frame, Itemp1, Isigma);
    cvConvertScale(Isigma, Isigma, 0.5);
    cvSub(frame, Isigma, Itemp1);
    cvSub(Itemp1, Isigma, Itemp2);
    cvMul(Itemp1, Itemp1, Itemp1);
    cvMul(Itemp2, Itemp2, Itemp2);
    cvAdd(Itemp1, Itemp2, Isigma);
    cvConvertScale(Isigma, Isigma, 0.5);

    while (1) {
        alpha = learningRate / 100.0;
        k = K / 10.0;
        
        //Calculate μ(t+1) = αF(t) + (1-α)μ(t)
        cvConvertScale(frame, Itemp1, alpha);
        cvConvertScale(Imu, Itemp2, 1 - alpha);
        cvAdd(Itemp1, Itemp2, ImuNext);

        //Calculate [σ(t+1)]^2 = α[F(t) - μ(t)]^2 + (1-α)[σ(t)]^2
        cvSub(frame, Imu, Itemp1);
        cvMul(Itemp1, Itemp1, Itemp1);
        cvConvertScale(Itemp1, Itemp1, alpha);
        //---
        cvConvertScale(Isigma, Itemp2, 1 - alpha);
        //---
        cvAdd(Itemp1, Itemp2, IsigmaNext);

        //Evaluate |F-μ|>Kσ
        cvAbsDiff(frame, Imu, frame);
        //---
        cvConvertScale(Isigma, Itemp_StdDeviation, 1);
        cvPow(Itemp_StdDeviation, Itemp_StdDeviation, 0.5);
        cvConvertScale(Itemp_StdDeviation, Itemp_StdDeviation, k);
        //---
        cvConvertScale(frame, Itemp3, 1);
        cvCmp(Itemp3, Itemp_StdDeviation, frame, CV_CMP_GT);
        
        cvShowImage("Original", frameTemp);
        cvShowImage("Running Gaussian Average", frame);

        char c = cvWaitKey(33);
        if (c == 27)
            break;

        cvCopy(ImuNext, Imu);
        cvCopy(IsigmaNext, Isigma);

        frameTemp = cvQueryFrame(capture);
        if (!frameTemp)
            break;
        cvCvtColor(frameTemp, frame, CV_RGB2GRAY);
    }
    cvReleaseImage(&frame);
    cvReleaseImage(&Itemp1);
    cvReleaseImage(&Itemp2);
    cvReleaseImage(&Itemp3);
    cvReleaseImage(&Itemp_StdDeviation);

    cvDestroyWindow("Original");
    cvDestroyWindow("Running Gaussian Average");

    deallocateImage();
}

void RunningGaussianAverage::deallocateImage()
{
    cvReleaseImage(&Imu);
    cvReleaseImage(&ImuNext);
    cvReleaseImage(&Isigma);
    cvReleaseImage(&IsigmaNext);
}

标签: pythonc++opencv

解决方案


我使用以下转换表为您的函数创建了一个类:

# cvQueryFrame --> retval, img = cv2.VideoCapture.read([image]) 
# cvGetSize --> rows, cols, _ = img.shape
# cvCreateImage -->  numpy.zeros((w,h,d), dtype='type')
# cvZero --> numpy.ndarray.fill(0)  <- you can merge this with the previous line
# cvCvtColor --> cv2.cvtColor(src, dst, cv2.COLOR_...)
# cvAbsDiff --> dst = numpy.absolute(src1, src2)  
# cvAdd --> cv2.add(src1, src2, dst) or dst = src1 + src2 
# cvMul --> cv2.multiply(src1, src2, dst, ...) or dst = numpy.multiply(src1, src2)
# cvPow --> dst = math.sqrt(src)
# cvCmp --> cv2.compare(src1, src2, dst, criterion)

决定cvPow()是因为您只使用它一次来执行sqrt().

还将代码从 opencv 2.x 更新到 opencv 4.x 再到 python 引入了一些差异:你没有显式使用类型,在真正使用它们之前不需要声明变量,::并且->成为.,等等. 两个版本的许多函数名称也发生了一些变化。这并不容易。

class RunningGaussianAverage:
    def __init__(self):
        self.learningRate = 5
        self.K = 20
        self.Imu = None
        self.ImuNext = None
        self.Isigma = None
        self.IsigmaNext = None

    def runningGaussianAverage(self, capture):
        # GUI part
        cv2.namedWindow("Original")
        cv2.namedWindow("Running Gaussian Average")

        cv2.createTrackbar("LearningRate", "Running Gaussian Average", self.learningRate, 100, None)
        cv2.createTrackbar("K", "Running Gaussian Average", self.K, 100, None)

        retval, frameTemp = cv2.VideoCapture(capture).read()  # get frame
        h = frameTemp.shape[0]  # substitute of 'sz'
        w = frameTemp.shape[1]  # substitute of 'sz'

        # init everything to empty frames
        self.Imu = np.zeros((h, w, 1), np.uint8)  # cvCreateImage(sz, IPL_DEPTH_8U, 1)
        self.ImuNext = np.zeros((h, w, 1), np.uint8)  # i replaced it trying to create a black image, 1 channel
        self.Isigma = np.zeros((h, w, 1), np.uint8)
        self.IsigmaNext = np.zeros((h, w, 1), np.uint8)

        Itemp2 = np.zeros((h, w, 1), np.uint8)

        # warning! opencv uses BGR convention!
        Itemp1 = cv2.cvtColor(frameTemp, cv2.COLOR_BGR2GRAY)  # convert to grayscale
        retval, frameTemp = cv2.VideoCapture(capture).read  # get another frame
        frame = cv2.cvtColor(frameTemp, cv2.COLOR_BGR2GRAY)  # convert to grayscale

        self.Imu = np.absolute(frame, Itemp1)  # absdiff

        # using opencv functions
        cv2.add(frame, Itemp1, self.Isigma)
        self.Isigma = self.Isigma * 0.5  # cvConvertScale(Isigma, Isigma, 0.5)
        cv2.subtract(frame, self.Isigma, Itemp1)
        cv2.subtract(Itemp1, self.Isigma, Itemp2)
        cv2.multiply(Itemp1, Itemp1, Itemp1)
        cv2.multiply(Itemp2, Itemp2, Itemp2)
        cv2.add(Itemp1, Itemp2, self.Isigma)
        self.Isigma = self.Isigma * 0.5  # cvConvertScale(Isigma, Isigma, 0.5)

        # using numpy arrays
        # self.Isigma = frame + Itemp1
        # self.Isigma = self.Isigma * 0.5
        # Itemp1 = frame - self.Isigma
        # Itemp2 = Itemp1 - self.Isigma
        # Itemp1 = Itemp1 * Itemp1
        # Itemp2 = Itemp2 * Itemp2
        # self.Isigma = Itemp1 + Itemp2
        # self.Isigma = self.Isigma * 0.5

        while True:
            alpha = self.learningRate / 100.0
            k = self.K / 10.0

            # Calculate μ(t+1) = αF(t) + (1-α)μ(t)
            Itemp1 = frame * alpha
            Itemp2 = self.Imu * (1 - alpha)

            # self.ImuNext = Itemp1 + Itemp2
            cv2.add(Itemp1, Itemp2, self.ImuNext)

            # Calculate[σ(t+1)] ^ 2 = α[F(t) - μ(t)] ^ 2 + (1-α)[σ(t)] ^ 2
            # Itemp1 = frame - self.Imu
            # Itemp1 = Itemp1 * Itemp1
            cv2.subtract(frame, self.Imu, Itemp1)
            cv2.multiply(Itemp1, Itemp1, Itemp1)
            Itemp1 = Itemp1 * alpha

            # ---
            Itemp2 = self.Isigma * (1 - alpha)

            # ---
            cv2.add(Itemp1, Itemp2, self.IsigmaNext)
            # self.IsigmaNext = Itemp1 + Itemp2

            # Evaluate | F-μ | > Kσ
            frame = np.absolute(frame, self.Imu)  # absdiff
            # frame = abs(frame - self.Imu)

            # ---
            Itemp_StdDeviation = np.zeros((h, w, 1), np.float)
            Itemp_StdDeviation = self.Isigma * 1
            Itemp_StdDeviation = math.sqrt(Itemp_StdDeviation)
            Itemp_StdDeviation = Itemp_StdDeviation * k

            # ---
            Itemp3 = np.zeros((h, w, 1), np.float)
            Itemp3 = frame * 1
            frame = cv2.compare(Itemp3, Itemp_StdDeviation, cv2.CMP_GT)

            cv2.imshow("Original", frameTemp)
            cv2.imshow("Running Gaussian Average", frame)

            c = cv2.waitKey(33)
            if c == 27:
                break

            self.Imu = self.ImuNext.copy()
            self.Isigma = self.IsigmaNext.copy()

            retval, frameTemp = cv2.VideoCapture(capture).read()  # get another frame
            if not frameTemp:
                break

            cv2.cvtColor(frameTemp, frame, cv2.COLOR_BGR2GRAY)

        frame = None
        Itemp1 = None
        Itemp2 = None

        cv2.destroyWindow("Original")
        cv2.destroyWindow("Running Gaussian Average")

        self.deallocateImage()

    def deallocateImage(self):
        # don't know if you need the following because of the garbage collector
        self.Imu = None
        self.ImuNext = None
        self.Isigma = None
        self.IsigmaNext = None

推荐阅读