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

nagoHok

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

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

  • Посещение

  • Days Won

    1

Сообщения, опубликованные пользователем nagoHok


  1. Здравствуйте! Можете объяснить как для визуализации кадров полученых с камеры использовать Tick таймера? Никола написал в посте, что его использует.

    Не советую использовать для этого таймер, ибо в карте сообщений системы он стоит самый последний, лучше для этого организовать отдельный поток.


  2. Оч сырой код, но более 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;
    
    }
    
    

    post-1451-0-77747800-1331761781_thumb.pn

    • Like 1

  3. Отделить надо и это уже делается. Сейчас GDI в Windows оставлен только для совместимости. Я не уверен, что в Windows 8 полностью от него не откажутся. Он в какой-то степени удобен, но уже устарел.

    Мы же сейчас говорим о быстром выводе видео и всевозможных примитивов? Тогда GDI для этого не применяется уже давно: все плейеры его не используют. Он уже ушёл из этой области.

    Если говорить о пользовательском интерфейсе, то и тут GDI сдал свои позиции Aero (а это полигоны + текстуры). На Линуксах, как я уже писал постом выше, тоже давно отказываются от двумерной графики для пользовательских интерфейсов, обрабатываемой CPU, а выводят её с помощью OpenGL. Хочешь ещё примеры? Браузеры (!!!) используют аппаратное ускорение для рендеринга страниц.

    Если говорить о непосредственной обработке и выводе графики на монитор, тогда конечно ГДИ - это динозавр, но что бы распечатать, то теже самые Директы и ОпенДЖэли будут пользовать ГДИ.

    Мы об одном и томже только с разных сторон :)


  4. P.S. Думаю, что GDI надо оставить прошлому. А Брезенхама (Брезенхема или Брезенхейма) мы всё равно никогда не забудем.

    От ГДИ не уйти, это унификация всего вывода графики.

    Тут надо отделить мух от котлет, для чего нужен ГДИ и для чего нужны Директы и ОпенДЖеэли

    Если первый предоставляет простой механизм для вывода графической информации неважно на какое либо устройство, то вторые это мощные средства для обработки аудио и видио

    кратко как то так


  5. помоему было изначально понятно, что метод с таким же успехом найдет и фару вместо номерного знака.

    тут можно вводить только ограничения на высоту, ширину номерного знака и сделать такую же гистограмму не только по горизонтали, но и вертикали.

    хмм, я тут подумал что будет лучше сделать гистограмму для каждого отдельного "блока" вертикальной гистограммы.


  6. Так попробовал срезать значение гистограммы с помощью среднего значения и дисперсии, в принципе результат неплохой, сейчас подошел не посредственно к локализации пластины, что можете посоветовать?

    Прикладываю 3 картинки, в принципе на изображениях непосредственно от 3 до 5 областей где может находиться номерная пластина, как же выбрать нужную область?

    Спасибо за рание.

    post-1451-0-71043300-1314090231_thumb.jp

    post-1451-0-27551800-1314090242_thumb.jp

    post-1451-0-27303700-1314090250_thumb.jp


  7. Можно ещё сгладить гистограмму и найти все значения, которые удовлетворяют условию: x[i-1] < x > x[i+1]

    Но с дисперсией лучше.

    P.S. Всем: а вообще, MeanShift не для этого предназначен?

    MeanShift? а можно про него по конкретнее?


  8. Можно попробовать найти среднее и дисперсию, и уровень отсечения установить, скажем, на 2 сигма от среднего.

    Или установить минимальное количество локальных минимумов и пройти по гистограмме с некоторым шагом пока уровень отсечения не будет пересекать гистограмму заданное кол-во раз. Можно еще смотреть ширину пересечений.

    ну среднее - я понял что такое, а вот дисперсия? По точнее можно узнать как её готовить?


  9. это локальные максимумы.

    найти глобальный максимум, и выделить их задав уровень, например если > 90% от максимума и отстоит от максимума на какое то расcтояние dist, то локальный максимум.

    невсегда бывает корректно, порой глобальный максимум многократно превышает локальные, хотя для начала можно развивать и эту идею.


  10. это локальные максимумы.

    найти глобальный максимум, и выделить их задав уровень, например если > 90% от максимума и отстоит от максимума на какое то расcтояние dist, то локальный максимум.

    а глобальный максимум это я так понимаю наибольший всплеск на гистограмме?


  11. так, вернулся о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);
    
    	}	
    
    }

    • Like 1

  12. так тут походу разбора полетов возник вопрос

    интенсивность яркости у нас от 0 до 255, значения IplImage::imageData у нас char т.е. от -127 до 128, правильно ли будет для получения функции приобразовывать char к unsigned char? или это надуманно?


  13. Только int-ы на float или double поменяйте, иначе ничего гладкого не получится.

    С целочисленной арифметикой надо очень аккуратно работать иначе очень долго можно потом ошибку искать.

    Вот результат того же алгоритма но с вещественными значениями, имхо с интами было лучше)

    ЗЫ вывод надо менять алгоритм сглаживания.

    post-1451-0-59973400-1310628310_thumb.jp


  14. Нашел ошибку в реализации

    
    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);
    
            }
    
    }
    
    

    да сейчас придется поработать над сглаживанием

    post-1451-0-08639000-1310626694_thumb.jp


  15. значит ошибка где то в коде, т.к. график у вас получился правильный и там видно, что 2 участка где ф-ия почти не возрастает (по бокам), и "лесенка" (в середине).

    попробуйте еще шаг поменять, т.е. шаг =step то, y2=F(i+step) y1=F(i) и x2-x1=step, хотя не думаю, что это поможет.

    по большому счету вы уже сейчас можете определить границы таблички.

    взять какой то отступ(в % или константой), и пройтись от начала т.е. до точки 0+отступ (это будет начало таблички) и от конца до точки конец-отступ (это будет конец таблички).

    вообще метод кажется не особо надежным, обычно делают детектор движения(определяют движущийся объект-машину)+ Канни(или что то похожее) + поиск прямоугольника(таблички).

    да сейчас как раз эксперементирую, на счет надежности метода - это часть алгоритма локализации таблички, конечноже она будет будет работать совместно с детектором движения, хотя пока не стоит забегать в перед.


  16. ну производную, то в дискретном случае можно взять как (y2-y1)/(x2-x1).

    как сглаживать и зачем не знаю.

    Поясните пжл, что в данном случае 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);
    
    	}
    
    }
    
    

    правда получается сплошная линия, толи я опять что то не так сделал, толи флрмула производной не та.


  17. так ну вроде получилось заставить работать функцию, спасибо Smorodov, сейчас осталось взять от неё производные, и работать с локализацией пластины.

    Можно еще поработать со сглаживанием, но изначальная оптимизация ЗЛО! :D Хотя и в данном варианте быстродействие меня вполне устраивает.

    
    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;
    
    }
    
    

    post-1451-0-65047100-1310594207_thumb.jp

×