none
배포용 DLL 만드는 방법 질문입니다. RRS feed

  • 질문

  • http://www.sysnet.pe.kr/2/0/800 

    위 사이트를 참고하여 배포용 DLL을 만들고 있습니다.

    심플한 DLL 프로젝트에서는 런타임을 /MT로 수정하였을때 별 다른 문제가 없었지만 

    문자열 string 또는 char에서는 아래와 같이 많은 에러들이 뜨고 있습니다.

    1>------ Build started: Project: test_dll, Configuration: Debug Win32 ------
    1>Build started 2015-02-23 오후 7:03:20.
    1>InitializeBuildStatus:
    1>  Touching "Debug\test_dll.unsuccessfulbuild".
    1>ClCompile:
    1>  MathFunc.cpp
    1>c:\users\koo\documents\visual studio 2010\projects\test_dll - 복사본 - 복사본\debug\opencv\build\include\opencv2\flann\dist.h : warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
    1>c:\users\koo\documents\visual studio 2010\projects\test_dll - 복사본 - 복사본\debug\opencv\build\include\opencv2\flann\dist.h : warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
    1>c:\users\koo\documents\visual studio 2010\projects\test_dll - 복사본 - 복사본\debug\opencv\build\include\opencv2\flann\dist.h : warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
    1>c:\users\koo\documents\visual studio 2010\projects\test_dll - 복사본 - 복사본\debug\opencv\build\include\opencv2\flann\dist.h : warning C4819: The file contains a character that cannot be represented in the current code page (949). Save the file in Unicode format to prevent data loss
    1>c:\tesseract-ocr\tesseract-ocr\vs2008\include\leptonica\pix.h(169): warning C4305: 'initializing' : truncation from 'double' to 'const l_float32'
    1>c:\tesseract-ocr\tesseract-ocr\vs2008\include\leptonica\pix.h(171): warning C4305: 'initializing' : truncation from 'double' to 'const l_float32'
    1>c:\tesseract-ocr\tesseract-ocr\ccutil\platform.h(33): warning C4005: 'snprintf' : macro redefinition
    1>          c:\tesseract-ocr\tesseract-ocr\vs2008\include\leptonica\environ.h(277) : see previous definition of 'snprintf'
    1>ManifestResourceCompile:
    1>  All outputs are up-to-date.
    1>Link:
    1>     Creating library C:\Users\koo\Documents\Visual Studio 2010\Projects\test_dll - 복사본 - 복사본\Debug\test_dll.lib and object C:\Users\koo\Documents\Visual Studio 2010\Projects\test_dll - 복사본 - 복사본\Debug\test_dll.exp
    1>LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library
    1>DetectRegions.obj : error LNK2019: unresolved external symbol __CrtDbgReportW referenced in function "public: class cv::Mat & __thiscall std::vector<class cv::Mat,class std::allocator<class cv::Mat> >::operator[](unsigned int)" (??A?$vector@VMat@cv@@V?$allocator@VMat@cv@@@std@@@std@@QAEAAVMat@cv@@I@Z)
    1>MathFunc.obj : error LNK2001: unresolved external symbol __CrtDbgReportW
    1>Plate.obj : error LNK2001: unresolved external symbol __CrtDbgReportW
    1>libcpmtd.lib(stdthrow.obj) : error LNK2001: unresolved external symbol __CrtDbgReportW
    1>MathFunc.obj : error LNK2019: unresolved external symbol __free_dbg referenced in function "private: void __thiscall std::_Yarn<char>::_Tidy(void)" (?_Tidy@?$_Yarn@D@std@@AAEXXZ)
    1>libcpmtd.lib(xdebug.obj) : error LNK2001: unresolved external symbol __free_dbg
    1>libcpmtd.lib(locale0.obj) : error LNK2001: unresolved external symbol __free_dbg
    1>libcpmtd.lib(xdebug.obj) : error LNK2019: unresolved external symbol __malloc_dbg referenced in function "void * __cdecl operator new(unsigned int,struct std::_DebugHeapTag_t const &,char *,int)" (??2@YAPAXIABU_DebugHeapTag_t@std@@PADH@Z)
    1>libcpmtd.lib(locale0.obj) : error LNK2001: unresolved external symbol __malloc_dbg
    1>libcpmtd.lib(_tolower.obj) : error LNK2019: unresolved external symbol __calloc_dbg referenced in function __Getctype
    1>C:\Users\koo\Documents\Visual Studio 2010\Projects\test_dll - 복사본 - 복사본\Debug\test_dll.dll : fatal error LNK1120: 4 unresolved externals
    1>
    1>Build FAILED.
    1>
    1>Time Elapsed 00:00:01.98
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

    원인이 무었인가요? 혹시나 코드 필요하실까봐 올렸습니다. 코드를 고쳐달라는건 절대 아니고 원인을 모르겠습니다.

    p.s /MTd 또는 /MDd에서는 잘되어서 비주얼이 설치된 컴퓨터에서는 작동이 잘되는 DLL라이브러리지만

    /MT 또는 /MD로 설정했을때는 아까 적은 에러가 발생합니다.  조금이라도 의견을 말씀해주신다면 정말 감사하겠습니다.

    Plate.h

    #ifndef Plate_h
    #define Plate_h
    
    #include <string.h>
    #include <vector>
    
    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv\cvaux.h>
    
    
    using namespace std;
    using namespace cv;
    
    class Plate{
        public:
            Plate();
            Plate(Mat img, Rect pos);
            string str();
            Rect position;
            Mat plateImg;
            vector<char> chars;
            vector<Rect> charsPos;        
    };
    
    #endif

    plate.cpp

    #include "Plate.h"
    
    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv\cvaux.h>
    Plate::Plate(){
    }
    
    Plate::Plate(Mat img, Rect pos){
        plateImg=img;
        position=pos;
    }
    
    string Plate::str(){
        string result="";
        //Order numbers
        vector<int> orderIndex;
        vector<int> xpositions;
        for(int i=0; i< charsPos.size(); i++){
            orderIndex.push_back(i);
            xpositions.push_back(charsPos[i].x);
        }
        float min=xpositions[0];
        int minIdx=0;
        for(int i=0; i< xpositions.size(); i++){
            min=xpositions[i];
            minIdx=i;
            for(int j=i; j<xpositions.size(); j++){
                if(xpositions[j]<min){
                    min=xpositions[j];
                    minIdx=j;
                }
            }
            int aux_i=orderIndex[i];
            int aux_min=orderIndex[minIdx];
            orderIndex[i]=aux_min;
            orderIndex[minIdx]=aux_i;
            
            float aux_xi=xpositions[i];
            float aux_xmin=xpositions[minIdx];
            xpositions[i]=aux_xmin;
            xpositions[minIdx]=aux_xi;
        }
        for(int i=0; i<orderIndex.size(); i++){
            result=result+chars[orderIndex[i]];
        }
        return result;
    }

    DetectRegions.h

    #ifndef DetectRegions_h
    #define DetectRegions_h
    
    #include <string.h>
    #include <vector>
    
    #include "Plate.h"
    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv\cvaux.h>
    
    using namespace std;
    using namespace cv;
    
    class DetectRegions{
        public:
            DetectRegions();
            string filename;
            void setFilename(string f);
            bool saveRegions;
            bool showSteps;
    		bool showSteps2;
    		bool showSteps3;
    		bool showSteps4;
    		bool finalshowSteps;
    		bool morphologyEx_Close;
    		bool morphologyEx_GRADIENT;
    
    		Mat NumImg;
            vector<Plate> run(Mat input);
        private:
            vector<Plate> segment(Mat input);
            bool verifySizes(RotatedRect mr);
            Mat histeq(Mat in);
    };
    
    #endif

    DetectRegions.cpp

    ///*****************************************************************************
    //*   Number Plate Recognition using SVM and Neural Networks
    //******************************************************************************
    //*   by David Mill? Escriv? 5th Dec 2012
    //*   http://blog.damiles.com
    //******************************************************************************
    //*   Ch5 of the book "Mastering OpenCV with Practical Computer Vision Projects"
    //*   Copyright Packt Publishing 2012.
    //*   http://www.packtpub.com/cool-projects-with-opencv/book
    //*****************************************************************************/
    
    #include "DetectRegions.h"
    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv\cvaux.h>
    #include <opencv\ml.h>
    #include <iostream>
    #include <vector>
    #include <fstream>
    void DetectRegions::setFilename(string s) {
            filename=s;
    }
    
    DetectRegions::DetectRegions(){
        showSteps=false;
    	showSteps2=false;
    	showSteps3=false;
    	showSteps4=false;
    	finalshowSteps=false;
        saveRegions=false;
    	morphologyEx_Close=false;
    	morphologyEx_GRADIENT=false;
    }
    
    bool DetectRegions::verifySizes(RotatedRect mr){
    
        float error=0.4;
        //Spain car plate size: 52x11 aspect 4,7272
        float aspect=4.7272;
        //Set a min and max area. All other patchs are discarded
        int min= 15*aspect*15; // minimum area
        int max= 125*aspect*125; // maximum area
        //Get only patchs that match to a respect ratio.
        float rmin= aspect-aspect*error;
        float rmax= aspect+aspect*error;
    
        int area= mr.size.height * mr.size.width;
        float r= (float)mr.size.width / (float)mr.size.height;
        if(r<1)
            r= (float)mr.size.height / (float)mr.size.width;
    
        if(( area < min || area > max ) || ( r < rmin || r > rmax )){
            return false;
        }else{
            return true;
        }
    }
    
    Mat DetectRegions::histeq(Mat in)
    {
        Mat out(in.size(), in.type());
        if(in.channels()==3){
            Mat hsv;
            vector<Mat> hsvSplit;
            cvtColor(in, hsv, CV_BGR2HSV);
            split(hsv, hsvSplit);
            equalizeHist(hsvSplit[2], hsvSplit[2]);
            merge(hsvSplit, hsv);
            cvtColor(hsv, out, CV_HSV2BGR);
        }else if(in.channels()==1){
            equalizeHist(in, out);
        }
    
        return out;
    
    }
    
    vector<Plate> DetectRegions::segment(Mat input){
        vector<Plate> output;
    
        //convert image to gray
        Mat img_gray;
        cvtColor(input, img_gray, CV_BGR2GRAY);
    	if(showSteps)
            imshow("gray", img_gray);
        blur(img_gray, img_gray, Size(5,5));    
    	if(showSteps)
            imshow("blur", img_gray);
        //Finde vertical lines. Car plates have high density of vertical lines
        Mat img_sobel;
        Sobel(img_gray, img_sobel, CV_8U, 1, 0, 3, 1, 0, BORDER_DEFAULT);
        if(showSteps)
            imshow("Sobel", img_sobel);
    
        //threshold image
        Mat img_threshold;
        threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
        if(showSteps2)
            imshow("Threshold", img_threshold);
    
        //Morphplogic operation close
    
        Mat element = getStructuringElement(MORPH_RECT, Size(17, 3) );
    	if(morphologyEx_GRADIENT)
    	{
    		morphologyEx(img_threshold, img_threshold, CV_MOP_GRADIENT, element);
    		if(showSteps2)
    			imshow("GRADIENT", img_threshold);
    	}
    	if(morphologyEx_Close)
    	{
    		morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element);
    		if(showSteps2)
    			imshow("Close", img_threshold);
    	}
    
    
    
    	/////////////////////////////////////////////////////////
        //Find contours of possibles plates
    	//
        vector< vector< Point> > contours;
        findContours(img_threshold,
                contours, // a vector of contours
                CV_RETR_EXTERNAL, // retrieve the external contours
                CV_CHAIN_APPROX_NONE); // all pixels of each contours
    
        //Start to iterate to each contour founded
        vector<vector<Point> >::iterator itc= contours.begin();
        vector<RotatedRect> rects;
    
        //Remove patch that are no inside limits of aspect ratio and area.    
        while (itc!=contours.end()) {
            //Create bounding rect of object
            RotatedRect mr= minAreaRect(Mat(*itc));
            if( !verifySizes(mr)){
                itc= contours.erase(itc);
            }else{
                ++itc;
                rects.push_back(mr);
            }
        }
    ///////////////////////////////////////////////////////////////
        // Draw blue contours on a white image
        cv::Mat result;
        input.copyTo(result);
        cv::drawContours(result,contours,
                -1, // draw all contours
                cv::Scalar(255,0,0), // in blue
                1); // with a thickness of 1
    
        for(int i=0; i< rects.size(); i++){
    
            //For better rect cropping for each posible box
            //Make floodfill algorithm because the plate has white background
            //And then we can retrieve more clearly the contour box
            circle(result, rects[i].center, 3, Scalar(0,255,0), -1);
            //get the min size between width and height
            float minSize=(rects[i].size.width < rects[i].size.height)?rects[i].size.width:rects[i].size.height;
            minSize=minSize-minSize*0.5;
            //initialize rand and get 5 points around center for floodfill algorithm
            srand ( time(NULL) );
            //Initialize floodfill parameters and variables
            Mat mask;
            mask.create(input.rows + 2, input.cols + 2, CV_8UC1);
            mask= Scalar::all(0);
    		if(showSteps)
                imshow("MASK1", mask);
            int loDiff = 30;
            int upDiff = 30;
            int connectivity = 4;
            int newMaskVal = 255;
            int NumSeeds = 10;
            Rect ccomp;
            int flags = connectivity + (newMaskVal << 8 ) + CV_FLOODFILL_FIXED_RANGE + CV_FLOODFILL_MASK_ONLY;
            for(int j=0; j<NumSeeds; j++){
                Point seed;
                seed.x=rects[i].center.x + rand()%(int)minSize-(minSize/2);
                seed.y=rects[i].center.y + rand()%(int)minSize-(minSize/2);
                circle(result, seed, 1, Scalar(0,255,255), -1);
                int area = floodFill(input, mask, seed, Scalar(255,0,0), &ccomp, Scalar(loDiff, loDiff, loDiff), Scalar(upDiff, upDiff, upDiff), flags);
            }
            if(showSteps)
                imshow("MASK2", mask);
            //cvWaitKey(0);
    
            //Check new floodfill mask match for a correct patch.
            //Get all points detected for get Minimal rotated Rect
            vector<Point> pointsInterest;
            Mat_<uchar>::iterator itMask= mask.begin<uchar>();
            Mat_<uchar>::iterator end= mask.end<uchar>();
            for( ; itMask!=end; ++itMask)
                if(*itMask==255)
                    pointsInterest.push_back(itMask.pos());
    				
            RotatedRect minRect = minAreaRect(pointsInterest);
    
            if(verifySizes(minRect)){
                // rotated rectangle drawing 
                Point2f rect_points[4]; minRect.points( rect_points );
                for( int j = 0; j < 4; j++ )
                    line( result, rect_points[j], rect_points[(j+1)%4], Scalar(0,0,255), 1, 8 );    
    			//imshow("result", result);
                //Get rotation matrix
                float r= (float)minRect.size.width / (float)minRect.size.height;
                float angle=minRect.angle; 
                if(r<1)
                    angle=90.5+angle;
                Mat rotmat= getRotationMatrix2D(minRect.center, angle,1);
    			if(showSteps3)
    				imshow("rotmat", rotmat);
                //Create and rotate image
                Mat img_rotated;
    			//imshow("input", input);
                warpAffine(input, img_rotated, rotmat, input.size(), CV_INTER_CUBIC);
    			if(showSteps3)
    				imshow("img_rotated", img_rotated);
                //Crop image
                Size rect_size=minRect.size;
                if(r < 1)
                    swap(rect_size.width, rect_size.height);
                Mat img_crop;
                getRectSubPix(img_rotated, rect_size, minRect.center, img_crop);
    			if(showSteps3)
    				imshow("img_crop", img_crop); 
    			if(saveRegions)
    			{
    				imwrite("OCR\\01_img_crop\\"+filename+".jpg", img_crop);
    			}
    			/////////////////////////////////////////////////////////////
    
    			Point2f ptSource[4], ptPrespective[4];
    			ptSource[0]=Point2f(0,1);
    			ptSource[1]=Point2f(221,0);
    			ptSource[2]=Point2f(224,45);
    			ptSource[3]=Point2f(3,45);
    			ptPrespective[0]=Point2f(0,0);
    			ptPrespective[1]=Point2f(224,0);
    			ptPrespective[2]=Point2f(224,48);
    			ptPrespective[3]=Point2f(0,48);     
    			Mat mat = getPerspectiveTransform(ptSource, ptPrespective);  // 변환행렬 구하기
    			Mat WarpPer;
    			warpPerspective(img_crop, WarpPer, mat, img_crop.size());
    			if(showSteps3)
    			{
    				imshow("WarpPer", WarpPer); 
    			}
    			/////////////////////////////////////////////////////////////  
    			Mat resultResized;
                resultResized.create(110,520, CV_8UC3);
                resize(WarpPer, resultResized, resultResized.size(), 0, 0, INTER_CUBIC);
    			if(showSteps3)
    				imshow("resultResized", resultResized);  
    			imwrite("plate.jpg", resultResized);
    			
    			/////////////////////////////////////////////////////////////  
    			//Equalize croped image
                Mat grayResult;
                cvtColor(resultResized, grayResult, CV_BGR2GRAY); 
                blur(grayResult, grayResult, Size(10,10));
                grayResult=histeq(grayResult);
    	        output.push_back(Plate(grayResult,minRect.boundingRect()));
    			if(showSteps3)
    			{
    				imshow("grayResult", grayResult);  		
    			}	
    			if(saveRegions)
    			{
    				imwrite("OCR\\03_grayResult\\"+filename+".jpg", grayResult);
    			}
    			Mat thresholdResult;
    			threshold(grayResult, thresholdResult, 45, 255, CV_THRESH_BINARY);
    			if(showSteps3)
    			{	
    				imshow("thresholdResult", thresholdResult); 
    			}
    			if(saveRegions)
    			{
    				imwrite("OCR\\04_thresholdResult\\"+filename+".jpg", thresholdResult); 
    			}
    			Rect rect = Rect(35,5,450,100);
    			Mat ROI_plateimg = resultResized(rect);
    			if(showSteps4)
    			{
    				imshow("ROI_plateimg", ROI_plateimg); 
    			}
    			if(saveRegions)
    			{
    				imwrite("OCR\\05_ROI_plateimg\\"+filename+".jpg", ROI_plateimg);
    			}
    			Mat ROI_plategray;
    			cvtColor(ROI_plateimg, ROI_plategray, CV_BGR2GRAY); 
    			if(showSteps4)
    			{
    				imshow("ROI_plategray", ROI_plategray); 
    			}
    			blur(ROI_plategray, ROI_plategray, Size(7,7));
                grayResult=histeq(ROI_plategray);
    	        output.push_back(Plate(ROI_plategray,minRect.boundingRect()));
    			Mat ROI_platethreshold;
    			threshold(ROI_plategray, ROI_platethreshold, 65, 255, CV_THRESH_BINARY);
    			if(showSteps4)
    			{
    				imshow("ROI_platethreshold", ROI_platethreshold);
    			}
    			if(saveRegions)
    			{
    				imwrite("OCR\\06_ROI_platethreshold\\"+filename+".jpg", ROI_platethreshold);
    			}
    			uchar val=0;
    			int hist[450];
    			int sum=0;
    			for(int widx = 0; widx <ROI_platethreshold.cols; widx++)
    			{
    				for(int hidx = 0; hidx <ROI_platethreshold.rows; hidx++)
    				{
    					val = ROI_platethreshold.at<uchar>(hidx,widx);
    					sum=sum+val;
    				}
    				hist[widx]=sum/100;
    				sum=0;
    			}
    			int platenum[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    			int widthcnt=0;
    			int flag=0;
    			int numcnt=0;
    			int black=0;
    			int white=0;
    			for(int widx = 0; widx <ROI_platethreshold.cols; widx++)
    			{		
    				
    				//printf("%d,",hist[widx]);
    				if(hist[widx]==255)
    				{
    					if(black==1)
    
    					{
    						numcnt++;
    						//printf("\nflatenum = %d\n",numcnt);
    						black=0;
    					}
    				
    					if(numcnt < 2 )
    					{
    						platenum[numcnt*2]=widx;
    					}
    
    				}
    				else
    				{
    					if(numcnt < 2 )
    					{
    					platenum[numcnt*2+1]=widx;
    					black=1;
    					}
    				}
    			}
    			numcnt=3;
    			platenum[6]=platenum[3]+90;
    			for(int widx = platenum[6]; widx <ROI_platethreshold.cols; widx++)
    			{		
    				
    				//printf("%d,",hist[widx]);
    				if(hist[widx]==255)
    				{
    					if(black==1)
    					{
    						numcnt++;
    						//printf("\nflatenum = %d\n",numcnt);
    						black=0;
    					}
    				
    					if(numcnt < 7 )
    					{
    						platenum[numcnt*2]=widx;
    					}
    
    				}
    				else
    				{
    					if(numcnt < 7 )
    					{
    					platenum[numcnt*2+1]=widx;
    					black=1;
    					}
    				}
    			}
    			platenum[4]=platenum[3]+6;
    			platenum[5]=platenum[6]-48;
    			//printf("\n");
    			int platenum_check = 0;
    			for(int i =0; i<14; i++)
    			{
    				if(platenum[i]<=0)
    				{
    					platenum_check=0;
    					break;
    				}
    				else
    				{
    					platenum_check=1;
    				}
    			}
    			if(platenum_check==1)
    			{
    				Rect rect1 = Rect(platenum[0],0,platenum[1]-platenum[0]+3,100);
    				NumImg = ROI_plateimg(rect1);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_1.jpg", NumImg);
    				NumImg = ROI_plategray(rect1);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_1.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect1);
    				imwrite("word_1.jpg", NumImg);
    
    
    				Rect rect2 = Rect(platenum[2],0,platenum[3]-platenum[2]+3,100);
    				NumImg = ROI_plateimg(rect2);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_2.jpg", NumImg);
    				NumImg = ROI_plategray(rect2);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_2.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect2);
    				imwrite("word_2.jpg", NumImg);
    
    				Rect rect3 = Rect(platenum[4],10,platenum[5]-platenum[4]+3,80);
    				NumImg = ROI_plateimg(rect3);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_3.jpg", NumImg);
    				NumImg = ROI_plategray(rect3);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_3.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect3);
    				imwrite("word_3.jpg", NumImg);
    			
    				Rect rect4 = Rect(platenum[6],0,platenum[7]-platenum[6]+3,100);
    				NumImg = ROI_plateimg(rect4);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_4.jpg", NumImg);
    				NumImg = ROI_plategray(rect4);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_4.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect4);
    				imwrite("word_4.jpg", NumImg);
    
    				Rect rect5 = Rect(platenum[8],0,platenum[9]-platenum[8]+3,100);
    				NumImg = ROI_plateimg(rect5);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_5.jpg", NumImg);
    				NumImg = ROI_plategray(rect5);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_5.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect5);
    				imwrite("word_5.jpg", NumImg);
    
    				Rect rect6 = Rect(platenum[10],0,platenum[11]-platenum[10]+3,100);
    				NumImg = ROI_plateimg(rect6);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_6.jpg", NumImg);
    				NumImg = ROI_plategray(rect6);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_6.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect6);
    				imwrite("word_6.jpg", NumImg);
    
    				Rect rect7 = Rect(platenum[12],0,platenum[13]-platenum[12]+2,100);
    				NumImg = ROI_plateimg(rect7);
    				//imwrite("OCR\\07_NumImg\\normal\\normal_7.jpg", NumImg);
    				NumImg = ROI_plategray(rect7);
    				//imwrite("OCR\\07_NumImg\\gray\\gray_7.jpg", NumImg);
    				NumImg = ROI_platethreshold(rect7);
    				imwrite("word_7.jpg", NumImg);
    			}
    			waitKey(0);
            }
        }       
        if(finalshowSteps) 
            imshow("result", result);
        return output;
    }
    
    vector<Plate> DetectRegions::run(Mat input){
        
        //Segment image by white 
        vector<Plate> tmp=segment(input);
    
        //return detected and posibles regions
        return tmp;
    }

    MathFunc.cpp

    #include <opencv\cv.h>
    #include <opencv\highgui.h>
    #include <opencv\cvaux.h>
    #include <opencv\ml.h>
    #include <iostream>
    #include <vector>
    #include "allheaders.h"
    #include "baseapi.h"
    #include "DetectRegions.h"
    #include <fstream>
    #include "string_32.h"
    #include <stdlib.h>  // _MAX_PATH, free()
    #include <direct.h>  // _getcwd()
    #include <crtdbg.h>
    #include <string.h>
    #include <Windows.h>
    #include <stdio.h>
    using namespace cv;
    using namespace std;
    
    string getFilename(string s) {
    
        char sep = '/';
        char sepExt='.';
    
        #ifdef _WIN32
            sep = '\\';
        #endif
    
        size_t i = s.rfind(sep, s.length( ));
        if (i != string::npos) {
            string fn= (s.substr(i+1, s.length( ) - i));
            size_t j = fn.rfind(sepExt, fn.length( ));
            if (i != string::npos) {
                return fn.substr(0,j);
            }else{
                return fn;
            }
        }else{
            return "";
        }
    }
    #define MAX_STR_LEN 4000
    // 문자열 우측 공백문자 삭제 함수
    char* rtrim(char* s) {
      char t[MAX_STR_LEN];
      char *end;
    
      // Visual C 2003 이하에서는
      // strcpy(t, s);
      // 이렇게 해야 함
      strcpy_s(t, s); // 이것은 Visual C 2005용
      end = t + strlen(t) - 1;
      while (end != t && isspace(*end))
        end--;
      *(end + 1) = '\0';
      s = t;
    
      return s;
    }
    
    // 문자열 좌측 공백문자 삭제 함수
    char* ltrim(char *s) {
      char* begin;
      begin = s;
    
      while (*begin != '\0') {
        if (isspace(*begin))
          begin++;
        else {
          s = begin;
          break;
        }
      }
    
      return s;
    }
    
    // 문자열 앞뒤 공백 모두 삭제 함수
    char* trim(char *s) {
      return rtrim(ltrim(s));
    }
    ///////////////////////////////
    //
    ///////////////////////////////////
    #define EXPORTDLL extern "C" __declspec(dllexport)
    EXPORTDLL void copyMessage(char * _input);
    void FindPlate(char* filename)
    {
        Mat input_image;
    	input_image=imread(filename,1);
    	string filename_whithoutExt=getFilename(filename);
        DetectRegions detectRegions;    
        detectRegions.setFilename(filename_whithoutExt);
        detectRegions.saveRegions=true;
    	detectRegions.morphologyEx_Close=true;
    	detectRegions.morphologyEx_GRADIENT=true;
        vector<Plate> posible_regions= detectRegions.run(input_image); 
    
    }
    
    EXPORTDLL void FileInput(char * _input)
    {
    	FindPlate(_input);
    }
    
    char* space="\n";
    char* kor = "customeng9";
    tesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();
    tesseract::TessBaseAPI *api2 = new tesseract::TessBaseAPI();
    EXPORTDLL void DetectWord1_2()
    {
    	const char* s;
    	char* getcwd;
    	getcwd = _getcwd(NULL, 0);
    	string s2=string(getcwd);
    	string s3;
    	s3="\\tesseract-ocr\\Pro Files\\Tesseract-OCR";
    	string str;
    	str+=s2;
    	str+=s3;
    	s=str.c_str();
    	/////////////////////////////////////////////////////////
    	//Word 1,2
    	////////////////////////////////////////////////////////
        if (api->Init(s, "eng")) {
            fprintf(stderr, "Could not initialize tesseract.\n");
            exit(1);
        }
    	Pix *image;
    	image=pixRead("word_1.jpg");
    	api->SetImage(image);
    	char *outtext1 = api->GetUTF8Text();
    	outtext1 = trim(outtext1);
    	if(outtext1[0] == 'A')
    	{
    		outtext1="4";
    	}
    	else if(outtext1[0] == 'S')
    	{
    		outtext1="5";
    	}
    	ofstream SaveFile1_2("plate_NumWord1_2.txt");
    	SaveFile1_2 << outtext1;
    	SaveFile1_2 << space;
    	//////////////////////////////
    	image=pixRead("word_2.jpg");
    	api->SetImage(image);
    	char *outtext2 = api->GetUTF8Text();
    	outtext2 = trim(outtext2);
    	if(outtext2[0] == 'A')
    	{
    		outtext2="4";
    	}
    	else if(outtext2[0] == 'S')
    	{
    		outtext2="5";
    	}
    	SaveFile1_2 << outtext2;
    	SaveFile1_2 << space;
    	SaveFile1_2.close();
    }
    /////////////////////////////////////////////////////////
    EXPORTDLL void DetectWord3()
    {
    	SetErrorMode(SEM_NOGPFAULTERRORBOX); 
    	const char* s;
    	char* getcwd;
    	getcwd = _getcwd(NULL, 0);
    	string s2=string(getcwd);
    	string s3;
    	s3="\\tesseract-ocr\\Pro Files\\Tesseract-OCR";
    	string str;
    	str+=s2;
    	str+=s3;
    	s=str.c_str();
    	Pix *image;
    	ofstream SaveFile3("plate_NumWord3.txt");
    	if (api2->Init(s, kor)) {
            fprintf(stderr, "Could not initialize tesseract.\n");
            exit(1);
        }
    	Mat Word3_img = imread("word_3.jpg");
    	Mat Word3_gray;
    	cvtColor(Word3_img, Word3_gray, CV_BGR2GRAY); 
    	Mat Word3_threshold;
    	threshold(Word3_gray, Word3_threshold, 70, 255, CV_THRESH_BINARY);
    	imwrite("word_3_2.jpg", Word3_threshold);
    	image=pixRead("word_3.jpg");
    	api2->SetImage(image);
    	char *outtext3=NULL;
    	outtext3 = api2->GetUTF8Text();
    	///////////////////////////////////////////////////////
    	//Word 3 - Error1
    	///////////////////////////////////////////////////////
    	char *uh = "uh\n\n";
    	char *muh = "muh\n\n";
    	char *o = "o\n\n";
    	char *oo = "0\noo";
    	char *mo = "mo\n\n";
    	char *ho = "ho\n\n";
    	char *jo = "j\no\n\n";
    	char *bo = "b\no\n\n";
    	char *mo2 = "m\no\n\n";
    	char *shift = "\n";
    	if(!strcmp(outtext3,uh) || !strcmp(outtext3,muh) || !strcmp(outtext3,o) || !strcmp(outtext3,mo) || !strcmp(outtext3,ho))
    	{
    		outtext3=NULL;
    		if (api2->Init(s, "customeng2")) {
    			fprintf(stderr, "Could not initialize tesseract.\n");
    			exit(1);
    		}
    		api2->SetImage(image);
    		outtext3 = api2->GetUTF8Text();
    	}
    	if(!strcmp(outtext3,jo))
    	{
    		outtext3 ="jo";
    	}
    	if(!strcmp(outtext3,bo))
    	{
    		outtext3 ="bo";
    	}	
    	////////////////////////////////////////////////////////
    	//Word 3 - Error2
    	///////////////////////////////////////////////////////
    	int no1 = 0;
    	int no2 = 0;
    	switch(outtext3[0])
    	{
    		case 'n':
    			no1++;
    			break;
    		case 'd':
    			no1++;
    			break;
    	}
    	switch(outtext3[1])
    	{
    		case 'o':
    			no2++;
    			break;
    		case '\n':
    			no2++;
    			break;
    	}
    	switch(outtext3[2])
    	{
    		case '\n':
    			no1++;
    			break;
    		case 'n':
    			no1++;
    			break;
    	}
    	switch(outtext3[3])
    	{
    		case 'n':
    			no2++;
    			break;
    		case '\n':
    			no2++;
    			break;
    	}
    	if(no1==2 && no2 == 2)
    	{
    		outtext3="no";
    	}
    	uchar val=0;
    	int hist[200];
    	int sum=0;
    	int hidx = 0;
    	int widx = 0;
    	int platenum[14]={0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    	int widthcnt=0;
    	int flag=0;
    	int numcnt=0;
    	int numcnt2=0;
    	int black=0;
    	int white=0;
    	for(hidx = 0; hidx <Word3_threshold.rows; hidx++)//행:세로
    	{
    		for(widx = 0; widx <Word3_threshold.cols; widx++)//열:가로
    		{
    			val = Word3_threshold.at<uchar>(hidx,widx);
    			sum=sum+val;
    		}
    		hist[hidx]=sum/Word3_threshold.cols;
    		sum=0;
    	}
    	for(hidx = 0; hidx <Word3_threshold.rows; hidx++)//행:세로
    	{
    		if(hist[hidx]==255)
    		{
    			if(black==1)
    			{
    				numcnt2++;
    				black=0;
    			}
    		}
    		else
    		{
    			black=1;
    		}
    	}
    	sum=0;
    	hidx = 0;
    	widx = 0;
    	widthcnt=0;
    	flag=0;
    	numcnt=0;
    	black=0;
    	white=0;
    	if(numcnt2 > 1)
    	{
    		outtext3=NULL;
    		if (api2->Init(s, "son-par")) {
    			fprintf(stderr, "Could not initialize tesseract.\n");
    			exit(1);
    		}
    		api2->SetImage(image);
    		outtext3 = api2->GetUTF8Text();
    		if((outtext3[2]=='o' && outtext3[3]=='o')||((outtext3[3]=='o' && outtext3[4]=='o')))
    		{
    			for(hidx = 0; hidx <Word3_threshold.rows; hidx++)//행:세로
    			{		
    				if(hist[hidx]==255)
    				{
    					if(black==1)
    					{
    						numcnt++;
    						black=0;
    					}
    					platenum[numcnt*2]=hidx;
    				}
    				else
    				{
    					platenum[numcnt*2+1]=hidx;
    					black=1;
    				}
    			}
    			for(int i =0; i<14; i++)
    			{
    				printf("%d,",platenum[i]);
    			}
    			Rect rect1 = Rect(0,platenum[0],Word3_threshold.cols,platenum[1]-platenum[0]+3);
    			Mat NumImg = Word3_img(rect1);
    			NumImg = Word3_gray(rect1);
    			NumImg = Word3_threshold(rect1);
    			imwrite("word_3_1.jpg", NumImg);
    			Pix *Word3_Son=pixRead("word_3_1.jpg");
    			if (api2->Init(s, "son")) {
    				fprintf(stderr, "Could not initialize tesseract.\n");
    				exit(1);
    			}
    			api2->SetImage(Word3_Son);
    			char *outtext3_1 = api2->GetUTF8Text();
    			if(outtext3_1[0]=='0'){
    				outtext3[0]='o';
    				outtext3[1]='o';
    				outtext3[2]=NULL;
    				outtext3[3]=NULL;
    			}
    			else{
    				outtext3[0]=outtext3_1[0];
    				outtext3[1]='o';
    				outtext3[2]='o';
    				outtext3[3]=NULL;
    			}
    		}
    	}
    	if(!strcmp(outtext3,mo2))
    	{
    		outtext3 ="mo";
    	}
    	outtext3 = trim(outtext3);
    	if(!strcmp(outtext3,oo))
    	{
    		outtext3 ="oo";
    	}
    	//outtext3 = trim(outtext3);
    	SaveFile3 << "xxx";
    	SaveFile3 << space;
    	SaveFile3 << outtext3;
    	SaveFile3 << space;
    	SaveFile3 << "xxx";
    	SaveFile3.close();
    }
    /////////////////////////////////////////////////////////
    EXPORTDLL void DetectWord4_7()
    {
    	
    	const char* s;
    	char* getcwd;
    	getcwd = _getcwd(NULL, 0);
    	string s2=string(getcwd);
    	string s3;
    	s3="\\tesseract-ocr\\Pro Files\\Tesseract-OCR";
    	string str;
    	str+=s2;
    	str+=s3;
    	s=str.c_str();
    	Pix *image;
    		ofstream SaveFile4_7("plate_NumWord4_7.txt");
    	if (api->Init(s, "eng")) {
            fprintf(stderr, "Could not initialize tesseract.\n");
            exit(1);
        }
    	image=pixRead("word_4.jpg");
    	api->SetImage(image);
    	char *outtext4 = api->GetUTF8Text();
    	outtext4 = trim(outtext4);
    	if(outtext4[0] == 'A')
    	{
    		outtext4="4";
    	}
    	else if(outtext4[0] == 'S')
    	{
    		outtext4="5";
    	}
    	SaveFile4_7 << outtext4;
    	SaveFile4_7 << space;
    	image=pixRead("word_5.jpg");
    	api->SetImage(image);
    	char *outtext5 = api->GetUTF8Text();
    	outtext5 = trim(outtext5);
    	if(outtext5[0] == 'A')
    	{
    		outtext5="4";
    	}
    	else if(outtext5[0] == 'S')
    	{
    		outtext5="5";
    	}
    	SaveFile4_7 << outtext5;
    	SaveFile4_7 << space;
    	image=pixRead("word_6.jpg");
    	api->SetImage(image);
    	char *outtext6 = api->GetUTF8Text();
    	outtext6 = trim(outtext6);
    	if(outtext6[0] == 'A')
    	{
    		outtext6="4";
    	}
    	else if(outtext6[0] == 'S')
    	{
    		outtext6="5";
    	}
    	SaveFile4_7 << outtext6;
    	SaveFile4_7 << space;
    	image=pixRead("word_7.jpg");
    	api->SetImage(image);
    	char *outtext7 = api->GetUTF8Text();
    	outtext7 = trim(outtext7);
    	if(outtext7[0] == 'A')
    	{
    		outtext7="4";
    	}
    	else if(outtext7[0] == 'S')
    	{
    		outtext7="5";
    	}
    	SaveFile4_7 << outtext7;
    	SaveFile4_7 << space;
    	api->End();
    	SaveFile4_7.close();
    
    }
    

    • 편집됨 koo2 2015년 2월 23일 월요일 오전 10:08
    2015년 2월 23일 월요일 오전 9:59

모든 응답

  • p.s /MTd 또는 /MDd에서는 잘되어서 비주얼이 설치된 컴퓨터에서는 작동이 잘되는 DLL라이브러리지만

    /MT 또는 /MD로 설정했을때는 아까 적은 에러가 발생합니다.  조금이라도 의견을 말씀해주신다면 정말 감사하겠습니다.

    라고 알려주셨는데요, 즉 그 말은 MTd 또는 MDd는 뒤에 d가 붙어서 디버그용 lib를 링크합니다. 그리고 MT 또는 MD는 릴리즈용 lib를 사용하구요. 즉, 지금 릴리즈용 C런타임 라이브러리를 사용하면 링크 에러가 발생한다는 뜻인데요, 첨부해 주신 코드를 보면 opencv 외부 라이브러리를 함께 사용하시는 것으로 보입니다. 

    일단 unicode를 사용하시는지, MBCS를 사용하시는지 빌드 설정에서 명확하게 설정하시고 해당 환경에 맡게 코드를 수정하셔서 유니코드관련 경고를 없애보시기 바랍니다. 그리고, 링크하시는 opencv를 디버그 버전 말고 릴리즈 버전으로 링크해서 다시 rebuild 해보시기 바랍니다.

    2015년 3월 10일 화요일 오전 6:02