Как рассчитать периметр двоичного изображения с помощью OpenCV 4.2 в C ++ - PullRequest
0 голосов
/ 21 апреля 2020

Я хочу вычислить периметр белого пятна в двоичном изображении размером 512 * 512. Изображение будет иметь только один шарик. Я использовал следующий код ранее в OpenCV 3, но почему-то он не работает в OpenCV 4.2. IplImage устарело в последней версии. И я не могу передать объект Mat напрямую функции cvFindContours. Я новичок в opencv, и я не знаю, как это работает. Другие связанные вопросы, касающиеся периметра, до сих пор остаются без ответа.

В итоге, следующие работы в opencv 3, но не работают в текущей версии opencv (4.2).

 int getPerimeter(unsigned char* inImagePtr, int inW, int inH)
    {
        int sumEven = 0; int sumOdd = 0;
        int sumCorner = 0; int prevCode = 0;

        //create a mat input Image
        cv::Mat inImage(inH, inW, CV_8UC1, inImagePtr);
            //create four connected structuring element
        cv::Mat element = cv::Mat::zeros(3, 3, CV_8UC1);
        element.data[1] = 1; element.data[3] = 1;
        element.data[4] = 1; element.data[5] = 1;
        element.data[7] = 1;

        //erode input image
        cv::Mat erodeImage;
        erode(inImage, erodeImage, element);
        //Invert eroded Image
        cv::threshold(erodeImage, erodeImage, 0, 255, THRESH_BINARY_INV);
        //multiply with original binary Image to get the edge Image
        cv::Mat edge = erodeImage.mul(inImage);

        //Get chain code of the blob
        CvChain* chain = 0;
        CvMemStorage* storage = 0;
        storage = cvCreateMemStorage(0);
        auto temp = new IplImage(edge);
        cvFindContours(temp, storage, (CvSeq**)(&chain), sizeof(*chain), CV_RETR_EXTERNAL, CV_CHAIN_CODE);
        delete temp;
        for (; chain != NULL; chain = (CvChain*)chain->h_next)
        {
            CvSeqReader reader;
            int i, total = chain->total;
            cvStartReadSeq((CvSeq*)chain, &reader, 0);
            for (i = 0; i < total; i++)
            {
                char code;
                CV_READ_SEQ_ELEM(code, reader);
                if (code % 2 == 0)
                    sumEven++;
                else
                    sumOdd++;
                if (i > 0) {
                    if (code != prevCode)
                        sumCorner++;
                }
                prevCode = code;
            }
        }
        float perimeter = (float)sumEven*0.980 + (float)sumOdd*1.406 - (float)sumCorner*0.091;
        return (roundf(perimeter));
    }
...