Пишу программу по распознаванию двух типов документов, использую для этого каскад Хаара, сам каскад раотает хорошо, проблем по распознаванию нет, но есть проблема с утечкеой памяти.
- Код: Выделить всё
//////////////////////////////////Заголовочные функции//////////////////////////////////
#include <opencv2/opencv.hpp> //модуль обработки изображений и компьютерного зрения
#include <opencv2/highgui.hpp> //ввод/вывод изображений и видео, захват видео и т.п.
#include <stdlib.h> //функции, занимающиеся выделением памяти, контроль процесса выполнения программы, преобразования типов и другие.
#include <stdio.h> //определения макросов, константы и объявления функций и типов
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <algorithm>
#include <iostream>
#include <math.h>
/////////////////////////////Используемые пространства имен/////////////////////////////
using namespace std;
using namespace cv;
/////////////////////////////Переменные (глобальные)/////////////////////////////
IplImage* frame=0; //для вывода изображения с камеры, цветное изображение
IplImage* gray = 0; //перевод видео в ч/б
Mat grayMat; // для поиска каскадом Хаара A
Mat grayMatB; // для поиска каскадом Хаара Б
IplImage* gray2 = 0; //вывод обработанного видео
int main(int argc, char* argv[])
{
CvCapture* capture = cvCreateCameraCapture(CV_CAP_ANY); //получаем любую подключённую камеру
assert( capture ); //прекращение программы с выводом ошибки согласно условию в скобках, если условие ложно
// задаем требуемое разрешение
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);//1280);
//cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);//960);
printf("[i] press Esc for quit!\n");
// узнаем ширину и высоту кадра. Выводим в консоль
double width = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); //ширина
double height = cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); //высота
printf("[i] %.0f x %.0f\n", width, height ); //выводим значения ширины и высоты
cvNamedWindow("capture", CV_WINDOW_AUTOSIZE); //создаем окно для отображения картинки
CascadeClassifier cascadeSymbol; // Объявление каскада A
bool cascadeSymbolLoad = cascadeSymbol.load("/home/pi/Desktop/SAP_1.0/Haar/cascade_A.xml"); // Загрузка каскада
assert( cascadeSymbolLoad );
CascadeClassifier cascadeSymbolB; // Объявление каскада Б
bool cascadeSymbolLoadB = cascadeSymbolB.load("/home/pi/Desktop/SAP_1.0/Haar/cascade_B.xml"); // Загрузка каскада
assert( cascadeSymbolLoadB );
while(true){ //бесконечный цикл для отображения кадров видео
frame = cvQueryFrame( capture ); // получаем кадр
gray = cvCreateImage(cvGetSize(frame), 8, 1);
cvCvtColor(frame, gray, CV_RGB2GRAY); //переводим в ч/б
/////////////////////////////////////////////////////////////////////////////////////////
grayMat = cvarrToMat(gray);
vector<Rect> symbols;
cascadeSymbol.detectMultiScale(grayMat, symbols); // Поиск с помощью каскада
for (int i = 0; i < symbols.size(); ++i)
{
Rect& p = symbols[i];
Point symbolBegin = Point(p.x, p.y);
Point symbolEnd = Point(p.x+p.width, p.y+p.height);
cout << "X: " << p.x << " Y: " << p.y << " Width: " << p.width << " Height: " << p.height << endl;
rectangle(grayMat, symbolBegin, symbolEnd, Scalar(0,255,0), 2);
///////////////////////////////////////////////////////////////
// Текстовый буффер
char text_buf[32];
//Текст в массив
sprintf(text_buf, "A");
//Шрифт
CvFont font;
cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX,1.0, 1.0, 0, 1, CV_AA);
//Вывод текста
IplImage itog;
gray = &(itog = grayMat);
cvPutText(gray, text_buf, cvPoint(p.x + 50 + p.width, p.y + 50), &font, cvScalar(0,0,255));
///////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////////////
gray2 = cvCloneImage(gray); //промежуточное изображение
grayMatB = cvarrToMat(gray2);
vector<Rect> symbolsB;
cascadeSymbolB.detectMultiScale(grayMatB, symbolsB); // Поиск с помощью каскада
for (int y = 0; y < symbolsB.size(); ++y)
{
Rect& z = symbolsB[y];
Point symbolBeginB = Point(z.x, z.y);
Point symbolEndB = Point(z.x+z.width, z.y+z.height);
cout << "X: " << z.x << " Y: " << z.y << " Width: " << z.width << " Height: " << z.height << endl;
rectangle(grayMatB, symbolBeginB, symbolEndB, Scalar(0,255,0), 2);
///////////////////////////////////////////////////////////////
// Текстовый буффер
char text_buf[32];
//Текст в массив
sprintf(text_buf, "B");
//Шрифт
CvFont font;
cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX,1.0, 1.0, 0, 1, CV_AA);
//Вывод текста
IplImage itogB;
gray = &(itogB = grayMatB);
cvPutText(gray2, text_buf, cvPoint(z.x + 50 + z.width, z.y + 50), &font, cvScalar(0,0,255));
///////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////////////
cvShowImage("capture", gray2); // показываем в ранее созданном окне
char c = cvWaitKey(33); // ждем нажатия клавиши
if (c == 27) break; //выход из цикла если нажат ESC
}
cvReleaseImage(&gray2);
cvReleaseImage(&gray);
cvReleaseCapture( &capture ); //освобождаем память
cvDestroyAllWindows(); //удаляем созданные окна для отображения
return 0; //по завершению программы возвращаем ноль
}
Если перенести строки
- Код: Выделить всё
cvReleaseImage(&gray2);
cvReleaseImage(&gray);
в конец цикла
- Код: Выделить всё
for (int i = 0; i < symbols.size(); ++i)
То утечка памяти исчезает, но при распознавании символа происходит вылет с ошибкой:
- Код: Выделить всё
[i] press Esc for quit!
[i] 640 x 480
X: 346 Y: 173 Width: 36 Height: 24
OpenCV Error: Bad argument (unrecognized or unsupported array type) in cvReleaseData, file /home/pi/opencv/modules/core/src/array.cpp, line 1010
terminate called after throwing an instance of 'cv::Exception'
what(): /home/pi/opencv/modules/core/src/array.cpp:1010: error: (-5) unrecognized or unsupported array type in function cvReleaseData
Но просто видео (до момента распознавания) выводит сколь угодно долго без каких-либо проблем.