Перейти к содержимому
Compvision.ru

nagoHok

Пользователи
  • Количество публикаций

    54
  • Зарегистрирован

  • Посещение

  • Days Won

    1

Все публикации пользователя nagoHok

  1. Не советую использовать для этого таймер, ибо в карте сообщений системы он стоит самый последний, лучше для этого организовать отдельный поток.
  2. я этими пользуюсь 1.rar
  3. Оч сырой код, но более 50% локализует, предлагаю довести его до ума) #include "stdafx.h" #include "ContrastMap.h" #pragma warning (disable:4996) #include <cv.h> #include <opencv2\highgui\highgui_c.h> #include <math.h> #pragma comment(lib,"opencv_core220d.lib") #pragma comment(lib,"opencv_highgui220d.lib") #pragma comment(lib,"opencv_imgproc220d.lib") #pragma comment(lib,"opencv_video220d.lib") #pragma comment(lib,"opencv_legacy220d.lib") #ifdef _DEBUG #define new DEBUG_NEW #endif // The one and only application object CWinApp theApp; using namespace std; class CBlock { public: int m_nStartPoin; int m_nEndPoint; int m_nBlockLen; CBlock(void) { m_nStartPoin = 0; m_nEndPoint = 0; m_nBlockLen = 0; } virtual ~CBlock(void) { } void Empty() { m_nStartPoin = 0; m_nEndPoint = 0; m_nBlockLen = 0; } bool IsNull(){return m_nBlockLen ? false : true;} }; void SummRow(const IplImage* pSrc, CArray<double>& arRow) { arRow.RemoveAll(); arRow.SetSize(pSrc->height); for (int nPosY = 0; nPosY < pSrc->height; nPosY++) { int nOffset = pSrc->widthStep * nPosY; for (int nPosX = 0; nPosX < pSrc->widthStep; nPosX++) { arRow[nPosY] += (uchar)pSrc->imageData[nOffset + nPosX]; } } } void DrawGraf(IplImage* pSrc, const CArray<double>& arRow) { CvPoint ptLastPoint = cvPoint(0, 0); for (int nPos = 0; nPos < arRow.GetCount(); nPos++) { cvDrawLine(pSrc, ptLastPoint, cvPoint((int)arRow[nPos] / 200, nPos) , cvScalar(0), 1); ptLastPoint = cvPoint((int)arRow[nPos] / 200, nPos); } } void AplyFilter(const IplImage* pSrc, IplImage* pDest) { double arMask[9] = {0,0,0,0,0.5,0,0,0,0}; //double arSharp[9] = {0.1111, -0.8889, 0.1111, -0.8889, 4.1111, -0.8889, 0.1111, -0.8889, 0.1111}; CvMat matMask = cvMat(3, 3, CV_64FC1, arMask); cvFilter2D(pSrc, pDest, &matMask, cvPoint(-1,-1)); } void AplySobel(const IplImage* pScr, IplImage* pDest) { IplImage* pDst = cvCreateImage( cvSize(pScr->width, pScr->height), IPL_DEPTH_16S, pScr->nChannels); // применяем оператор Собеля cvSobel(pScr, pDst, 1, 0, 3); // преобразуем изображение к 8-битному cvConvertScale(pDst, pDest); cvReleaseImage(&pDst); } inline double GSmooth(double nDist, double nParam, double nParam2) { return exp((-(nDist * nDist)/nParam)) / nParam2; } void GauseSmooth(const CArray<double>& arSrc, CArray<double>& arDest) { arDest.RemoveAll(); double nParam = 3.; int nAperture = 5; double nParam1 = 2* (nParam * nParam); double nParam2 = sqrt(2 * CV_PI) * nParam; arDest.SetSize(arSrc.GetCount()); for (int nPos = 0; nPos < arSrc.GetCount() - 1; nPos++) { double s = 0.; for (int nK = max(nPos - nAperture, 0); nK < min(arSrc.GetCount() - 1, nPos + nAperture); nK++) { s += arSrc[nK] * GSmooth(abs(nPos - nK), nParam1, nParam2); } arDest.SetAt(nPos, s); } } void Func(IplImage* pImg, int nPosY, CArray<double>& arFunc) { arFunc.RemoveAll(); double _f = 0.; int nLinePos = nPosY * pImg->widthStep; arFunc.SetSize( pImg->widthStep - 1); for(int nPos = 0; nPos < pImg->widthStep - 1; nPos++) { _f += abs(pImg->imageData[nLinePos + nPos + 1] - pImg->imageData[nLinePos + nPos]); arFunc.SetAt(nPos, _f); } } void GetFirstDiff(const CArray<double>& arSrc, CArray<double>& arDest) { CArray<double> arTmp; arTmp.SetSize(arSrc.GetCount()); for (int nPos = 1; nPos < arSrc.GetCount(); nPos++) { if(nPos + 1 > arSrc.GetCount() - 1) continue; double ndY = arSrc[nPos + 1] - arSrc[nPos]; arTmp.SetAt(nPos, ndY); } arDest.RemoveAll(); arDest.Copy(arTmp); arTmp.RemoveAll(); } int GetMaxPosition(CArray<double>& arGraf) { int nMax = 0; for (int nPos = 0; nPos < arGraf.GetCount(); nPos++) { if(arGraf[nPos] > arGraf[nMax]) nMax = nPos; } return nMax; } void GetLocalMinMax(const CArray<double>& arData, CArray<int>& arPositionsMin, CArray<int>& arPositionsMax) { int nCount = 0; double nMin = 0, nMax = 0; bool bIsMaxF = false; bool bIsMinF = false; for(int nPos = 1; nPos < arData.GetCount() - 1; nPos++) { //Отслеживаем уменьшение. if ((nPos == 1) || (arData[nPos - 1] < arData[nPos])) { nMax = arData[nPos]; bIsMaxF = true; } if ((nPos == 1) || (arData[nPos - 1] > arData[nPos])) { nMin = arData[nPos]; bIsMinF = true; } //Если ранее было обнаружено уменьшение. if(bIsMaxF) { //Отслеживаем увеличение. if ((nPos == arData.GetCount() - 1) || (arData[nPos - 1] > arData[nPos])) { //Очередной локальный max найден. arPositionsMax.Add(nPos); nCount++; if(nCount == 1) nMin = nMax; else if(nMax < nMin) nMin = nMax; bIsMaxF = false; } } if(bIsMinF) { //Отслеживаем увеличение. if ((nPos == arData.GetCount() - 1) || (arData[nPos - 1] < arData[nPos])) { //Очередной локальный минимум найден. arPositionsMin.Add(nPos); nCount++; if(nCount == 1) nMax = nMin; else if(nMin > nMax) nMax = nMin; bIsMinF = false; } } } } void CalcBlocks(int nMinBlockLen, CArray<CBlock>& m_arWidthBlock, double nAvVal, const CArray<double>& arData) { m_arWidthBlock.RemoveAll(); CBlock block; int nSpaces = 0; for (int nPos = 0; nPos < arData.GetCount(); nPos++) { if(arData[nPos] >= nAvVal) { if(block.m_nStartPoin) { block.m_nBlockLen++; nSpaces = 0; } else { block.m_nStartPoin = nPos; block.m_nBlockLen++; nSpaces = 0; } } else { if(block.m_nStartPoin) { if(nSpaces >= nMinBlockLen) { block.m_nEndPoint = nPos - nSpaces; block.m_nBlockLen -= nSpaces; nSpaces = 0; m_arWidthBlock.Add(block); block.Empty(); continue; } nSpaces++; } } } if(block.m_nStartPoin) { block.m_nEndPoint = arData.GetCount() - nSpaces; m_arWidthBlock.Add(block); } } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { IplImage* pFrame = NULL; //Захваченый фрейм IplImage* pGray = NULL; //Фрейм приведенный к серому цвету IplImage* pGrath = NULL; //Тут рисуем графики CFileFind finder; //BOOL bWorking = finder.FindFile(_T("c:/Utils/Работа/Мое/Распознание/Саша/Day/*.*")); BOOL bWorking = finder.FindFile(_T("C:/Users/Я/Desktop/Avto-Control Demo/Images/Day/*.*")); while (bWorking) { bWorking = finder.FindNextFile(); if(!bWorking) break; CStringA strFileName(finder.GetFilePath()); if(finder.IsDots()) continue; TRACE(strFileName.GetString()); TRACE(_T("\n")); pFrame = cvLoadImage(strFileName); if(!pFrame) continue; DWORD dwStart = GetTickCount(); cvSmooth(pFrame, pFrame, CV_GAUSSIAN, 3, 3); //Создаем серое изображение pGray = cvCreateImage(cvGetSize(pFrame), 8, 1); cvConvertImage(pFrame, pGray, CV_BGR2GRAY); //Выравниваем яркость изображения cvEqualizeHist(pGray, pGray); CArray<double> arGraf; AplySobel(pGray, pGray); SummRow(pGray, arGraf); int nMaxPos = GetMaxPosition(arGraf); CArray<double> arFunc; Func(pGray, nMaxPos, arFunc); CArray<double> arSmooth; //GauseSmooth(arFunc, arSmooth); CArray<double> arDif; GetFirstDiff(arFunc, arDif); CArray<int> arMins; CArray<int> arMaxs; GetLocalMinMax(arDif, arMins, arMaxs); int nMaxFromMax = GetMaxPosition(arDif); double nAvValMax = arDif[nMaxFromMax] * 0.2; CArray<CBlock> arBlocks; CalcBlocks(20, arBlocks, nAvValMax, arDif); /* for (int nPos = 0; nPos < arMaxs.GetCount(); nPos++) { nAvValMax += arDif[arMaxs[nPos]]; }*/ //nAvValMax = nAvValMax / arMaxs.GetCount(); //nAvValMax = nAvValMax + nAvValMax * 0.2; pGrath = cvCreateImage(cvGetSize(pFrame), 8, 1); DrawGraf(pFrame, arGraf); CvPoint ptLast = cvPoint(0, nMaxPos); int nCount = 0; // for (int nPos = 0; nPos < arDif.GetCount(); nPos++) // { // //if(arDif[nPos] < nAvValMax) // //{ // // //cvDrawLine(pGrath, cvPoint(nPos, nMaxPos), cvPoint(nPos, nMaxPos - (int)(arDif[nPos])), cvScalar(0), 1); // // continue; // //} // // nCount++; // cvDrawLine(pFrame, cvPoint(nPos, nMaxPos), cvPoint(nPos, nMaxPos + (int)(arDif[nPos] / 5)), cvScalar(0), 1); // ///* // int nPosY = (nMaxPos + (int)arDif[nPos] / 5); // cvDrawLine(pGrath, ptLast, cvPoint(nPos, nPosY), cvScalar(0), 1); // ptLast = cvPoint(nPos, nPosY); //*/ // } for (int nPos = 0; nPos < arBlocks.GetCount(); nPos++) { CBlock &block = arBlocks[nPos]; int nHigh = (int)(block.m_nEndPoint - block.m_nStartPoin) / 9.2; if(arBlocks[nPos].m_nBlockLen < 10 || arBlocks[nPos].m_nBlockLen > 100) continue; cvDrawRect(pFrame, cvPoint(arBlocks[nPos].m_nStartPoin - 10, nMaxPos - nHigh), cvPoint(arBlocks[nPos].m_nEndPoint + 10, nMaxPos + nHigh), cvScalar(255), 2); } std::cout << nCount << " " << GetTickCount() - dwStart << std::endl ; cvNamedWindow("Graf"); cvShowImage("Graf", pFrame); cvReleaseImage(&pGray); cvReleaseImage(&pFrame); cvReleaseImage(&pGrath); char c = cvWaitKey(0); if (c == 27) { break; } } return 0; }
  4. Если говорить о непосредственной обработке и выводе графики на монитор, тогда конечно ГДИ - это динозавр, но что бы распечатать, то теже самые Директы и ОпенДЖэли будут пользовать ГДИ. Мы об одном и томже только с разных сторон
  5. От ГДИ не уйти, это унификация всего вывода графики. Тут надо отделить мух от котлет, для чего нужен ГДИ и для чего нужны Директы и ОпенДЖеэли Если первый предоставляет простой механизм для вывода графической информации неважно на какое либо устройство, то вторые это мощные средства для обработки аудио и видио кратко как то так
  6. пока все в процессе Сразу попутный вопрос, можно ли произвести фильтрацию изначального изображения КИХ фильтром?
  7. так ну получается примерно следующее
  8. хмм, я тут подумал что будет лучше сделать гистограмму для каждого отдельного "блока" вертикальной гистограммы.
  9. Так попробовал срезать значение гистограммы с помощью среднего значения и дисперсии, в принципе результат неплохой, сейчас подошел не посредственно к локализации пластины, что можете посоветовать? Прикладываю 3 картинки, в принципе на изображениях непосредственно от 3 до 5 областей где может находиться номерная пластина, как же выбрать нужную область? Спасибо за рание.
  10. MeanShift? а можно про него по конкретнее?
  11. ну среднее - я понял что такое, а вот дисперсия? По точнее можно узнать как её готовить?
  12. невсегда бывает корректно, порой глобальный максимум многократно превышает локальные, хотя для начала можно развивать и эту идею.
  13. а глобальный максимум это я так понимаю наибольший всплеск на гистограмме?
  14. Может кто нибудь подскажет алгоритм, как выдилить из всей гисторгаммы следующие скачки (выделил их на рисунке) Я так понимаю это вроде как глобальные максимумы? Спасибо за рание.
  15. так, вернулся о5 таки к проекту, удалось сгладить полученую функци, но быстродействие оставляет желать лучшего, с тем учотом что еше надо и локализовать область номерного знака а затем попытаться распознать символы если кому интересна вот реализации сглаживающей функции inline double GausSmooth(double nDist, double nParam, double nParam2) { return exp((-(nDist * nDist)/nParam)) / nParam2; } void SmoothFunc1(const CArray<_Line>& arSrc, CArray<_Line>& arDest) { arDest.RemoveAll(); double nParam = 15.; int nAperture = 50; double nParam1 = 2* (nParam * nParam); double nParam2 = sqrt(2 * CV_PI) * nParam; for(int nPosY = 0; nPosY < arSrc.GetCount() - 1; nPosY++) { _Line line; line = arSrc[nPosY]; for (int nPosX = 0; nPosX < arSrc[nPosY].GetSize() - 1; nPosX++) { double s = 0.; for (int nK = max(nPosX - nAperture, 0); nK < min(arSrc[nPosY].GetSize() - 1, nPosX + nAperture); nK++) { s += arSrc[nPosY].Get(nK) * GausSmooth(abs(nPosX - nK), nParam1, nParam2); } line.SetAt(nPosX, s); } arDest.Add(line); } }
  16. я изначально конвертирую изображение к градации серого ЗЫ я не спрашиваю как, меня интересует надо ли это делать?
  17. так тут походу разбора полетов возник вопрос интенсивность яркости у нас от 0 до 255, значения IplImage::imageData у нас char т.е. от -127 до 128, правильно ли будет для получения функции приобразовывать char к unsigned char? или это надуманно?
  18. работает то неплохо, но далек от реального времени.
  19. так а как определить длинну номера тогда? К томуже если при движение размеры плитки будут меняться?
  20. Вот результат того же алгоритма но с вещественными значениями, имхо с интами было лучше) ЗЫ вывод надо менять алгоритм сглаживания.
  21. Нашел ошибку в реализации void GetFirstDiff(const CArray<_Line>& arSrc, CArray<_Line>& arDest) { arDest.RemoveAll(); for (int nPosY = 0; nPosY < arSrc.GetCount(); nPosY++) { _Line line; line.SetSize(arSrc[nPosY].GetSize()); line.m_nYPosition = arSrc[nPosY].m_nYPosition; for (int nPosX = 0; nPosX < arSrc[nPosY].GetSize() - 2; nPosX++) { int nDiff = 0; int nY = arSrc[nPosY].m_nYPosition; if(nPosX + 1 > arSrc[nPosY].GetSize()) return; int ndY = (nY - arSrc[nPosY].m_arData[nPosX + 1]) - (nY - arSrc[nPosY].m_arData[nPosX]); int ndX = nPosX + 1 - nPosX; //Можно и не делить if(ndX) //Так как шаг всегда 1 nDiff = ndY / ndX; line.m_arData[nPosX] = nDiff; } arDest.Add(line); } } да сейчас придется поработать над сглаживанием
  22. да сейчас как раз эксперементирую, на счет надежности метода - это часть алгоритма локализации таблички, конечноже она будет будет работать совместно с детектором движения, хотя пока не стоит забегать в перед.
  23. втом то и дело, что я реализовал, но график производной - прямая т.е. разница приращения y2-y1 всего 1 пиксель
  24. Поясните пжл, что в данном случае y2 y1, x2 x1? Спасибо за рание! Утро вечера мудренее void GetFirstDiff(const CArray<_Line>& arSrc, CArray<_Line>& arDest) { arDest.RemoveAll(); for (int nPosY = 0; nPosY < arSrc.GetCount(); nPosY++) { _Line line; line.SetSize(arSrc[nPosY].GetSize()); line.m_nYPosition = arSrc[nPosY].m_nYPosition; for (int nPosX = 0; nPosX < arSrc[nPosY].GetSize() - 2; nPosX++) { int nDiff = 0; int nY = arSrc[nPosY].m_nYPosition; if(nPosX + 1 > arSrc[nPosY].GetSize()) return; int ndY = (nY - arSrc[nPosY].m_arData[nPosX + 1]) - (nY - arSrc[nPosY].m_arData[nPosX]); int ndX = arSrc[nPosY].m_arData[nPosX + 1] - arSrc[nPosY].m_arData[nPosX]; if(ndX) nDiff = ndY / ndX; line.m_arData[nPosX] = nDiff; } arDest.Add(line); } } правда получается сплошная линия, толи я опять что то не так сделал, толи флрмула производной не та.
  25. так ну вроде получилось заставить работать функцию, спасибо Smorodov, сейчас осталось взять от неё производные, и работать с локализацией пластины. Можно еще поработать со сглаживанием, но изначальная оптимизация ЗЛО! Хотя и в данном варианте быстродействие меня вполне устраивает. class _Line { int m_nSize; public: _Line() :m_nSize(0) ,m_nYPosition(0) {}; virtual ~_Line(){}; CArray<int> m_arData; int GetSize() const {return m_nSize;}; void SetSize(int nSize) { if(nSize <= 0) return; m_nSize = nSize; m_arData.SetSize(m_nSize, 10); } _Line& operator = (const _Line& src) { SetSize(src.m_nSize); m_nYPosition = src.m_nYPosition; m_arData.Copy(src.m_arData); return *this; } int m_nYPosition; }; void SmoothFunc(const CArray<_Line>& arSrc, CArray<_Line>& arDest) { arDest.RemoveAll(); for (int nPosY = 0; nPosY < arSrc.GetCount(); nPosY++) { _Line line; line.SetSize(arSrc[nPosY].GetSize()); line.m_nYPosition = arSrc[nPosY].m_nYPosition; for (int nPosX = 0; nPosX < arSrc[nPosY].GetSize() - 2; nPosX++) { int nSmooth = 0; for (int nSmoothPos = -2; nSmoothPos < 3; nSmoothPos++) { if(nPosX < 2 && nSmoothPos < 0) continue; nSmooth += arSrc[nPosY].m_arData[nPosX + nSmoothPos]; } nSmooth /= 5; line.m_arData[nPosX] = nSmooth; } arDest.Add(line); } } void Func(IplImage* pImg, int nPosY, _Line& line) { unsigned int _f = 0; int nLinePos = nPosY * pImg->widthStep; line.SetSize( pImg->widthStep - 1); for(int nPos = 0; nPos < pImg->widthStep - 1; nPos++) { _f += abs(pImg->imageData[nLinePos + nPos + 1] - pImg->imageData[nLinePos + nPos]); line.m_arData[nPos] = _f; } } int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { cvNamedWindow("Org"); cvNamedWindow("Gray"); IplImage* frame = NULL; frame = cvLoadImage("c:/test.jpg"); IplImage* gray = NULL; gray = cvCreateImage(cvGetSize(frame), 8, 1); cvConvertImage(frame, gray, CV_BGR2GRAY); CvPoint ptLast = cvPoint(0, 0); DWORD dwStart = GetTickCount(); int nLastYPos = 0; CArray<_Line> arLines; CArray<_Line> arLinesSmoth; for (int nY = 0; nY < gray->height; nY += 10) { //ptLast = cvPoint(0, nY); _Line line; line.m_nYPosition = nY; Func(gray, nY, line); arLines.Add(line); } SmoothFunc(arLines, arLinesSmoth); CArray<_Line> arDraw; arDraw.Copy(arLinesSmoth); for (int nPosY = 0; nPosY < arDraw.GetCount(); nPosY++) { if(nPosY != 46) //Убрать!!!! continue; //Убрать!!!! ptLast = cvPoint(0, arDraw[nPosY].m_nYPosition); for (int nPosX = 0; nPosX < arDraw[nPosY].GetSize(); nPosX++) { int f = arDraw[nPosY].m_arData[nPosX] / 50; cvLine(frame, ptLast, cvPoint(nPosX, arDraw[nPosY].m_nYPosition - f) , cvScalar(0), 1); ptLast = cvPoint(nPosX, arDraw[nPosY].m_nYPosition - f); } } dwStart = GetTickCount() - dwStart; std::cout << dwStart; cvShowImage("Gray", gray); cvShowImage("Org", frame); cvReleaseImage(&gray); cvReleaseImage(&frame); gray = NULL; frame = NULL; char c = cvWaitKey(0); if (c == 27) { return 0; } return 0; }
×