Ejemplo n.º 1
0
// 阈值分割
vector<CharSegment> OCR::segment(Plate plate) {
    Mat input = plate.plateImg;
    vector<CharSegment> output;
    Mat thresholdImage;
    threshold(input, thresholdImage, 60, 255, CV_THRESH_BINARY_INV);
    if (DEBUG)
        imshow("Threshold plate", thresholdImage);
    Mat img_contours;
    thresholdImage.copyTo(img_contours);
    // 找到可能的车牌的轮廓
    vector< vector< Point> > contours;
    findContours(img_contours,
                 contours, // 检测的轮廓数组,每一个轮廓用一个point类型的vector表示
                 CV_RETR_EXTERNAL, // 表示只检测外轮廓
                 CV_CHAIN_APPROX_NONE); // 轮廓的近似办法,这里存储所有的轮廓点

    // 在白色的图上画出蓝色的轮廓
    cv::Mat result;

    thresholdImage.copyTo(result);
    cvtColor(result, result, CV_GRAY2RGB);
    cv::drawContours(result, contours,
                     -1,  // 所有的轮廓都画出
                     cv::Scalar(255, 0, 0), // 颜色
                     1); // 线粗

    // 对每个轮廓检测和提取最小区域的有界矩形区域
    vector<vector<Point> >::iterator itc = contours.begin();

    char res[20];
    int i = 0;
    // 若没有达到设定的宽高比要求,移去该区域
    while (itc != contours.end())
    {
        Rect mr = boundingRect(Mat(*itc));
        rectangle(result, mr, Scalar(0, 255, 0));
        // 裁剪图像
        Mat auxRoi(thresholdImage, mr);
        if (verifySizes(auxRoi)) {
            auxRoi = preprocessChar(auxRoi);
            output.push_back(CharSegment(auxRoi, mr));
            //保存每个字符图片
            sprintf(res, "PlateNumber%d.jpg", i);
            i++;
            imwrite(res, auxRoi);
            rectangle(result, mr, Scalar(0, 125, 255));
        }
        ++itc;
    }
    if (DEBUG)
        cout << "Num chars: " << output.size() << "\n";

    if (DEBUG)
        imshow("SEgmented Chars", result);
    return output;
}
Ejemplo n.º 2
0
vector<SegmentoLetra> OCR::segmento(Placa plate){
	Mat input = plate.placaImg;
	vector<SegmentoLetra> output;
	//Threshold input image
	Mat img_threshold;
	threshold(input, img_threshold, 60, 255, CV_THRESH_BINARY_INV);
	if (DEBUG)
		imshow("Threshold plate", img_threshold);
	Mat img_contours;
	img_threshold.copyTo(img_contours);
	//Find contours of possibles characters
	vector< vector< Point> > contours;
	findContours(img_contours,
		contours, // a vector of contours
		CV_RETR_EXTERNAL, // retrieve the external contours
		CV_CHAIN_APPROX_NONE); // all pixels of each contours

	// Draw blue contours on a white image
	cv::Mat result;
	img_threshold.copyTo(result);
	cvtColor(result, result, CV_GRAY2RGB);
	cv::drawContours(result, contours,
		-1, // draw all contours
		cv::Scalar(255, 0, 0), // in blue
		1); // with a thickness of 1

	//Start to iterate to each contour founded
	vector<vector<Point> >::iterator itc = contours.begin();

	//Remove patch that are no inside limits of aspect ratio and area.    
	while (itc != contours.end()) {

		//Create bounding rect of object
		Rect mr = boundingRect(Mat(*itc));
		rectangle(result, mr, Scalar(0, 255, 0));
		//Crop image
		Mat auxRoi(img_threshold, mr);
		if (verificarTamaño(auxRoi)){
			auxRoi = preprocesamientoCaracter(auxRoi);
			output.push_back(SegmentoLetra(auxRoi, mr));
			rectangle(result, mr, Scalar(0, 125, 255));
		}
		++itc;
	}
	if (DEBUG)
		cout << "Num chars: " << output.size() << "\n";



	if (DEBUG)
		imshow("SEgmented Chars", result);
	return output;
}
Ejemplo n.º 3
0
//! 字符分割与排序
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
{
	if( !input.data )
	{ return -3; }

	//判断车牌颜色以此确认threshold方法
	int plateType = getPlateType(input);
	cvtColor(input, input, CV_RGB2GRAY);

	//Threshold input image
	Mat img_threshold;
	if (1 == plateType)
		threshold(input, img_threshold, 10, 255, CV_THRESH_OTSU+CV_THRESH_BINARY);
	else 
		threshold(input, img_threshold, 10, 255, CV_THRESH_OTSU+CV_THRESH_BINARY_INV);

	if(m_debug)
	{ 
		stringstream ss(stringstream::in | stringstream::out);
		ss << "image/tmp/debug_char_threshold" << ".jpg";
		imwrite(ss.str(), img_threshold);
	}

	//去除车牌上方的柳钉以及下方的横线等干扰
	clearLiuDing(img_threshold);


	if(m_debug)
	{ 
		stringstream ss(stringstream::in | stringstream::out);
		ss << "image/tmp/debug_char_clearLiuDing" << ".jpg";
		imwrite(ss.str(), img_threshold);
	}

	Mat img_contours;
	img_threshold.copyTo(img_contours);

	vector< vector< Point> > contours;
	findContours(img_contours,
		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<Rect> vecRect;

	//Remove patch that are no inside limits of aspect ratio and area.  
	//将不符合特定尺寸的图块排除出去
	while (itc != contours.end()) 
	{
		Rect mr = boundingRect(Mat(*itc));
		Mat auxRoi(img_threshold, mr);
		if (verifySizes(auxRoi))
		{
			vecRect.push_back(mr);
		}
		++itc;
	}
	
	if (vecRect.size() == 0)
		return -3;

	vector<Rect> sortedRect;
	//对符合尺寸的图块按照从左到右进行排序
	SortRect(vecRect, sortedRect);

	int specIndex = 0;
	//获得指示城市的特定Rect,如苏A的"A"
	specIndex = GetSpecificRect(sortedRect);

	if(m_debug)
	{ 
		if (specIndex < sortedRect.size())
		{
			Mat specMat(img_threshold, sortedRect[specIndex]);
			stringstream ss(stringstream::in | stringstream::out);
			ss << "image/tmp/debug_specMat" <<".jpg";
			imwrite(ss.str(), specMat);
		}
	}

	//根据特定Rect向左反推出中文字符
	//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能
	//退过特定算法来指定
	Rect chineseRect;
	if (specIndex < sortedRect.size())
		chineseRect = GetChineseRect(sortedRect[specIndex]);
	else
		return -3;

	if(m_debug)
	{ 
		Mat chineseMat(img_threshold, chineseRect);
		stringstream ss(stringstream::in | stringstream::out);
		ss << "image/tmp/debug_chineseMat" <<".jpg";
		imwrite(ss.str(), chineseMat);
	}


	//新建一个全新的排序Rect
	//将中文字符Rect第一个加进来,因为它肯定是最左边的
	//其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符
	vector<Rect> newSortedRect;
	newSortedRect.push_back(chineseRect);
	RebuildRect(sortedRect, newSortedRect, specIndex);

	if (newSortedRect.size() == 0)
		return -3;

	for (int i = 0; i < newSortedRect.size(); i++)
	{
		Rect mr = newSortedRect[i];
		Mat auxRoi(img_threshold, mr);

		if (1)
		{
			auxRoi = preprocessChar(auxRoi);
			if(m_debug)
			{ 
				stringstream ss(stringstream::in | stringstream::out);
				ss << "image/tmp/debug_char_auxRoi_" << i <<".jpg";
				imwrite(ss.str(), auxRoi);
			}
			resultVec.push_back(auxRoi);
		}
	}

	return 0;
}
Ejemplo n.º 4
0
	//! 字符分割与排序
	int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec)
	{
		// 输入图片无数据,返回ErrorCode=0x01
		if (!input.data)
			return 0x01;

		int w = input.cols;
		int h = input.rows;

		Mat tmpMat = input(Rect(w*0.1,h*0.1,w*0.8,h*0.8));

		//判断车牌颜色以此确认threshold方法
		Color plateType = getPlateType(tmpMat, true);

		Mat input_grey;
		cvtColor(input, input_grey, CV_BGR2GRAY);

		Mat img_threshold ;
		if (BLUE == plateType)
		{
			//cout << "BLUE" << endl;
			img_threshold = input_grey.clone();
			
			int w = input_grey.cols;
			int h = input_grey.rows;
			Mat tmp = input_grey(Rect(w*0.1,h*0.1,w*0.8,h*0.8));
			int threadHoldV = ThresholdOtsu(tmp);
			imwrite("E:/img_inputgray2.jpg",input_grey);
		
			threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY);
			imwrite("E:/img_threshold.jpg",img_threshold);

			//threshold(input_grey, img_threshold, 5, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);

		}
		else if (YELLOW == plateType)
		{
			//cout << "YELLOW" << endl;
			img_threshold = input_grey.clone();
			int w = input_grey.cols;
			int h = input_grey.rows;
			Mat tmp = input_grey(Rect(w*0.1,h*0.1,w*0.8,h*0.8));
			int threadHoldV = ThresholdOtsu(tmp);
			imwrite("./image/tmp/inputgray2.jpg",input_grey);

			threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY_INV);

			//threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
		}
		else if (WHITE == plateType)
		{
			//cout << "WHITE" << endl;
			/*img_threshold = input_grey.clone();
			int w = input_grey.cols;
			int h = input_grey.rows;
			Mat tmp = input_grey(Rect(w*0.1, h*0.1, w*0.8, h*0.8));
			int threadHoldV = ThresholdOtsu(tmp);
			imwrite("./image/tmp/inputgray2.jpg", input_grey);*/

			threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
		}
		else
		{
			//cout << "UNKNOWN" << endl;
			threshold(input_grey, img_threshold, 10, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
		}
		
		if (0)
		{
			imshow("threshold", img_threshold);
			waitKey(0);
			destroyWindow("threshold");
		}
		
		if (m_debug)
		{
			stringstream ss(stringstream::in | stringstream::out);
			ss << "image/tmp/debug_char_threshold" <<iTag<< ".jpg";
			imwrite(ss.str(), img_threshold);
		}

		// 去除车牌上方的柳钉以及下方的横线等干扰
		// 并且也判断了是否是车牌
		// 并且在此对字符的跳变次数以及字符颜色所占的比重做了是否是车牌的判别条件
		// 如果不是车牌,返回ErrorCode=0x02
		if (!clearLiuDing(img_threshold))
			return 0x02;

		if (m_debug)
		{
			stringstream ss(stringstream::in | stringstream::out);
			ss << "image/tmp/debug_char_clearLiuDing" <<iTag<< ".jpg";
			imwrite(ss.str(), img_threshold);
		}
		iTag++;


		Mat img_contours;
		img_threshold.copyTo(img_contours);

		vector< vector< Point> > contours;
		findContours(img_contours,
			contours, // a vector of contours
			CV_RETR_EXTERNAL, // retrieve the external contours
			CV_CHAIN_APPROX_NONE); // all pixels of each contours

		vector<vector<Point> >::iterator itc = contours.begin();
		vector<Rect> vecRect;

		// 将不符合特定尺寸的字符块排除出去
		while (itc != contours.end()) {
			Rect mr = boundingRect(Mat(*itc));
			Mat auxRoi(img_threshold, mr);

			if (verifyCharSizes(auxRoi))
				vecRect.push_back(mr);
			++itc;
		}

		// 如果找不到任何字符块,则返回ErrorCode=0x03
		if (vecRect.size() == 0)
			return 0x03;

		// 对符合尺寸的图块按照从左到右进行排序;

		/*vector<Rect> sortedRect;		
		SortRect(vecRect, sortedRect);*/

		vector<Rect> sortedRect(vecRect);
		std::sort(sortedRect.begin(), sortedRect.end(), [](const Rect &r1, const Rect &r2) {return r1.x < r2.x;});

		int specIndex = 0;

		//获得特殊字符对应的Rectt,如苏A的"A"
		specIndex = GetSpecificRect(sortedRect);

		if (m_debug)
		{
			if (specIndex < sortedRect.size())
			{
				Mat specMat(img_threshold, sortedRect[specIndex]);
				stringstream ss(stringstream::in | stringstream::out);
				ss << "image/tmp/debug_specMat" << ".jpg";
				imwrite(ss.str(), specMat);
			}
		}

		//根据特定Rect向左反推出中文字符
		//这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能
		//退过特定算法来指定
		Rect chineseRect;
		if (specIndex < sortedRect.size())
			chineseRect = GetChineseRect(sortedRect[specIndex]);
		else
			return -3;

		if (m_debug)
		{
			Mat chineseMat(img_threshold, chineseRect);
			stringstream ss(stringstream::in | stringstream::out);
			ss << "image/tmp/debug_chineseMat" << ".jpg";
			imwrite(ss.str(), chineseMat);
		}


		//新建一个全新的排序Rect
		//将中文字符Rect第一个加进来,因为它肯定是最左边的
		//其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符
		vector<Rect> newSortedRect;
		newSortedRect.push_back(chineseRect);
		RebuildRect(sortedRect, newSortedRect, specIndex);

		if (newSortedRect.size() == 0)
			return -3;

	
		for (int i = 0; i < newSortedRect.size(); i++)
		{
			Rect mr = newSortedRect[i];
			Mat auxRoi(img_threshold, mr);

			if (1)
			{
				auxRoi = preprocessChar(auxRoi);
				if (m_debug)
				{
					stringstream ss(stringstream::in | stringstream::out);
					ss << "image/tmp/debug_char_auxRoi_" << (i+staticIndex) << ".jpg";
					imwrite(ss.str(), auxRoi);
				}
				resultVec.push_back(auxRoi);
			}
		}
		staticIndex+=newSortedRect.size();

		return 0;
	}
Ejemplo n.º 5
0
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color) {
  if (!input.data) return 0x01;

  Mat input_grey;
  cvtColor(input, input_grey, CV_BGR2GRAY);

  if (1) {
    imshow("plate", input_grey);
    waitKey(0);
    destroyWindow("plate");
  }

  Mat img_threshold;

  // 二值化
  // 根据车牌的不同颜色使用不同的阈值判断方法
  // TODO:使用MSER来提取这些轮廓

  //if (BLUE == plateType) {
  //  // cout << "BLUE" << endl;
  //  img_threshold = input_grey.clone();

  //  int w = input_grey.cols;
  //  int h = input_grey.rows;
  //  Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
  //  int threadHoldV = ThresholdOtsu(tmp);
  //  threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY);

  //} else if (YELLOW == plateType) {
  //  // cout << "YELLOW" << endl;
  //  img_threshold = input_grey.clone();
  //  int w = input_grey.cols;
  //  int h = input_grey.rows;
  //  Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
  //  int threadHoldV = ThresholdOtsu(tmp);
  //  // utils::imwrite("resources/image/tmp/inputgray2.jpg", input_grey);

  //  threshold(input_grey, img_threshold, threadHoldV, 255,
  //            CV_THRESH_BINARY_INV);

  //} else if (WHITE == plateType) {
  //  // cout << "WHITE" << endl;

  //  threshold(input_grey, img_threshold, 10, 255,
  //            CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
  //} else {
  //  // cout << "UNKNOWN" << endl;
  //  threshold(input_grey, img_threshold, 10, 255,
  //            CV_THRESH_OTSU + CV_THRESH_BINARY);
  //}

  Color plateType = color;

  img_threshold = input_grey.clone();
  spatial_ostu(img_threshold, 8, 2, plateType);

  if (0) {
    imshow("plate", img_threshold);
    waitKey(0);
    destroyWindow("plate");
  }

  // 去除车牌上方的柳钉以及下方的横线等干扰
  // 并且也判断了是否是车牌
  // 并且在此对字符的跳变次数以及字符颜色所占的比重做了是否是车牌的判别条件
  // 如果不是车牌,返回ErrorCode=0x02

  if (!clearLiuDing(img_threshold)) return 0x02;
  //clearLiuDing(img_threshold);

  // 在二值化图像中提取轮廓

  Mat img_contours;
  img_threshold.copyTo(img_contours);

  vector<vector<Point> > contours;
  findContours(img_contours,
               contours,               // a vector of contours
               CV_RETR_EXTERNAL,       // retrieve the external contours
               CV_CHAIN_APPROX_NONE);  // all pixels of each contours

  vector<vector<Point> >::iterator itc = contours.begin();
  vector<Rect> vecRect;

  // 将不符合特定尺寸的字符块排除出去

  while (itc != contours.end()) {
    Rect mr = boundingRect(Mat(*itc));
    Mat auxRoi(img_threshold, mr);

    if (verifyCharSizes(auxRoi)) vecRect.push_back(mr);
    ++itc;
  }

  // 如果找不到任何字符块,则返回ErrorCode=0x03

  if (vecRect.size() == 0) return 0x03;

  // 对符合尺寸的图块按照从左到右进行排序;
  // 直接使用stl的sort方法,更有效率

  vector<Rect> sortedRect(vecRect);
  std::sort(sortedRect.begin(), sortedRect.end(),
            [](const Rect& r1, const Rect& r2) { return r1.x < r2.x; });

  size_t specIndex = 0;

  // 获得特殊字符对应的Rectt,如苏A的"A"

  specIndex = GetSpecificRect(sortedRect);

  // 根据特定Rect向左反推出中文字符
  // 这样做的主要原因是根据findContours方法很难捕捉到中文字符的准确Rect,因此仅能
  // 退过特定算法来指定

  Rect chineseRect;
  if (specIndex < sortedRect.size())
    chineseRect = GetChineseRect(sortedRect[specIndex]);
  else
    return 0x04;

  if (0) {
    rectangle(img_threshold, chineseRect, Scalar(255));
    imshow("plate", img_threshold);
    waitKey(0);
    destroyWindow("plate");
  }

  //新建一个全新的排序Rect
  //将中文字符Rect第一个加进来,因为它肯定是最左边的
  //其余的Rect只按照顺序去6个,车牌只可能是7个字符!这样可以避免阴影导致的“1”字符

  vector<Rect> newSortedRect;
  newSortedRect.push_back(chineseRect);
  RebuildRect(sortedRect, newSortedRect, specIndex);

  if (newSortedRect.size() == 0) return 0x05;

  // 开始截取每个字符

  for (size_t i = 0; i < newSortedRect.size(); i++) {
    Rect mr = newSortedRect[i];

    // Mat auxRoi(img_threshold, mr);

    // 使用灰度图来截取图块,然后依次对每个图块进行大津阈值来二值化

    Mat auxRoi(input_grey, mr);
    Mat newRoi;

    if (BLUE == plateType) {
      //newRoi = auxRoi.clone();
      //spatial_ostu(newRoi, 5, 5, plateType);
      if (i != 0) 
        threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY + CV_THRESH_OTSU);
      else
        adaptiveThreshold(auxRoi, newRoi, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, 0);
      
    } else if (YELLOW == plateType) {
      threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY_INV + CV_THRESH_OTSU);

    } else if (WHITE == plateType) {
      threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
    } else {
      threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
    }

    // 归一化大小
    newRoi = preprocessChar(newRoi);

    if (0) {
      if (i == 0) {
        imshow("chinese", newRoi);
        waitKey(0);
        destroyWindow("chinese");
      }
    }

    // 每个字符图块输入到下面的步骤进行处理
    resultVec.push_back(newRoi);
  }

  return 0;
}
Ejemplo n.º 6
0
 void CvScan::charsSegement( IplImage *src, vector<Mat> &vector){
     
     if (src == NULL) {
         return;
     }
     
     IplImage *pimg = cvCreateImage(cvSize(src->width*1.1, src->height*1.1), src->depth, src->nChannels);
     /*
     int m_otsu = otsu(pimg);
     printf("m_otsu:%d\n",m_otsu);
     cvReleaseImage(&pimg);
     pimg = cvCreateImage(cvGetSize(src), src->depth, src->nChannels);
     cvThreshold(src, pimg, m_otsu, 255, CV_THRESH_BINARY);
     //cvZero(pimg);
     //*/
     
     //IplImage imgHSV = *cvCreateImage(cvGetSize(pimg), 8, 1);
     //cv::Mat matImg(&imgHSV,true);
     
     cv::Mat img_contours(pimg->width,pimg->height,CV_8UC1,Scalar::all(0));
     img_contours.data = (uchar *)pimg->imageData;
     
     
     std::vector< std::vector< CvPoint> > contours;
     
     findContours(img_contours,
                  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
     std::vector<std::vector<CvPoint>>::iterator itc = contours.begin();
     std::vector<CvRect> vecRect;
     
     //Remove patch that are no inside limits of aspect ratio and area.
     //将不符合特定尺寸的图块排除出去
     while (itc != contours.end()){
         Rect mr = boundingRect(cv::Mat(*itc));
         cv::Mat auxRoi(img_contours, mr);
         if (verifyMatCharSizes(auxRoi))
             vecRect.push_back(mr);
         
         ++itc;
     }
     
     if (vecRect.size() == 0)
         return ;
     std::vector<CvRect> sortedRect;
     ////对符合尺寸的图块按照从左到右进行排序
     sortRect(vecRect, sortedRect);
     
     for (int i = 0; i < sortedRect.size(); i++){
         CvRect mr = sortedRect[i];
         cv::Mat auxRoi(img_contours, mr);
         
         auxRoi = preprocessChar(auxRoi);
         vector.push_back(auxRoi);
     }
     
     /* 另一个方法
     
     //*/
     return ;
 }
//Role: 	Detection des caractere dans une plaque
//Entrées:	la plaque d'immatriculation (entree/sortie)
//Sorties:	La meme plaque avec les caractere dans un vector<Chars>
void PlateRecognizer::CharactersDetection( Plate& plate )
{
	cv::Mat input = plate.GetImage();
	cv::Mat gray;
	cv::cvtColor( input, gray, cv::COLOR_BGR2GRAY );
	//Threshold input image
	cv::Mat img_threshold;
	cv::Canny( gray, img_threshold, 100, 100 * 2 );
	if ( showSteps )
	{
		imshow( "Threshold plate", img_threshold );
		cv::waitKey();
	}

	cv::Mat img_contours;
	img_threshold.copyTo( img_contours );
	//Find contours of possibles characters
	std::vector< std::vector< cv::Point> > contours;
	findContours( img_contours,
				  contours, // a vector of contours
				  CV_RETR_EXTERNAL, // retrieve the external contours
				  CV_CHAIN_APPROX_NONE ); // all pixels of each contours

	if ( showSteps )
	{
		imshow( "contours", img_contours );
		cv::waitKey();
	}

	// Draw blue contours on a white image
	cv::Mat result;
	img_threshold.copyTo( result );
	cvtColor( result, result, CV_GRAY2RGB );
	cv::drawContours( result, contours,
					  -1, // draw all contours
					  cv::Scalar( 255, 0, 0 ), // in blue
					  1 ); // with a thickness of 1

						   //Start to iterate to each contour founded
	std::vector<std::vector<cv::Point> >::iterator itc = contours.begin();
	if ( showSteps )
	{
		cv::imshow( "result", result );
		cv::waitKey();

	}
	//Remove patch that are no inside limits of aspect ratio and area.    
	while ( itc != contours.end() )
	{

		//Create bounding rect of object
		cv::Rect mr = cv::boundingRect( cv::Mat( *itc ) );
		rectangle( result, mr, cv::Scalar( 0, 255, 0 ) );
		//Crop image
		cv::Mat auxRoi( img_threshold, mr );
		if ( ValidateChar( auxRoi ) )
		{
			mr.x -= mr.x - 2.5 <= 0 ? 0 : 2.5;
			mr.y -= mr.y - 2.5 <= 0 ? 0 : 2.5;
			if ( mr.x + mr.width + 5 < img_threshold.size().width )
				mr.width += 5;
			if ( mr.y + mr.height + 5 < img_threshold.size().height )
				mr.height += 5;
			cv::Mat toprocess( img_threshold, mr );
			auxRoi = preprocessChar( toprocess );
			plate.AddChars( auxRoi, mr );
			rectangle( result, mr, cv::Scalar( 0, 125, 255 ) );
			if ( showSteps )
			{
				cv::imshow( "rectangle", result );
				cv::waitKey();
			}
		}
		++itc;
	}
}
Ejemplo n.º 8
0
int CCharsSegment::charsSegment(Mat input, vector<Mat>& resultVec, Color color) {
  if (!input.data) return 0x01;

  Color plateType = color;

  Mat input_grey;
  cvtColor(input, input_grey, CV_BGR2GRAY);

  if (0) {
    imshow("plate", input_grey);
    waitKey(0);
    destroyWindow("plate");
  }

  Mat img_threshold;


  //if (BLUE == plateType) {
  //  // cout << "BLUE" << endl;
  //  img_threshold = input_grey.clone();

  //  int w = input_grey.cols;
  //  int h = input_grey.rows;
  //  Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
  //  int threadHoldV = ThresholdOtsu(tmp);
  //  threshold(input_grey, img_threshold, threadHoldV, 255, CV_THRESH_BINARY);

  //} else if (YELLOW == plateType) {
  //  // cout << "YELLOW" << endl;
  //  img_threshold = input_grey.clone();
  //  int w = input_grey.cols;
  //  int h = input_grey.rows;
  //  Mat tmp = input_grey(Rect_<double>(w * 0.1, h * 0.1, w * 0.8, h * 0.8));
  //  int threadHoldV = ThresholdOtsu(tmp);
  //  // utils::imwrite("resources/image/tmp/inputgray2.jpg", input_grey);

  //  threshold(input_grey, img_threshold, threadHoldV, 255,
  //            CV_THRESH_BINARY_INV);

  //} else if (WHITE == plateType) {
  //  // cout << "WHITE" << endl;

  //  threshold(input_grey, img_threshold, 10, 255,
  //            CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
  //} else {
  //  // cout << "UNKNOWN" << endl;
  //  threshold(input_grey, img_threshold, 10, 255,
  //            CV_THRESH_OTSU + CV_THRESH_BINARY);
  //}

  img_threshold = input_grey.clone();
  spatial_ostu(img_threshold, 8, 2, plateType);

  if (0) {
    imshow("plate", img_threshold);
    waitKey(0);
    destroyWindow("plate");
  }

  // remove liuding and hor lines
  // also judge weather is plate use jump count

  if (!clearLiuDing(img_threshold)) return 0x02;
  //clearLiuDing(img_threshold);


  Mat img_contours;
  img_threshold.copyTo(img_contours);

  vector<vector<Point> > contours;
  findContours(img_contours,
               contours,               // a vector of contours
               CV_RETR_EXTERNAL,       // retrieve the external contours
               CV_CHAIN_APPROX_NONE);  // all pixels of each contours

  vector<vector<Point> >::iterator itc = contours.begin();
  vector<Rect> vecRect;

  while (itc != contours.end()) {
    Rect mr = boundingRect(Mat(*itc));
    Mat auxRoi(img_threshold, mr);

    if (verifyCharSizes(auxRoi)) vecRect.push_back(mr);
    ++itc;
  }


  if (vecRect.size() == 0) return 0x03;

  vector<Rect> sortedRect(vecRect);
  std::sort(sortedRect.begin(), sortedRect.end(),
            [](const Rect& r1, const Rect& r2) { return r1.x < r2.x; });

  size_t specIndex = 0;

  specIndex = GetSpecificRect(sortedRect);

  Rect chineseRect;
  if (specIndex < sortedRect.size())
    chineseRect = GetChineseRect(sortedRect[specIndex]);
  else
    return 0x04;

  if (0) {
    rectangle(img_threshold, chineseRect, Scalar(255));
    imshow("plate", img_threshold);
    waitKey(0);
    destroyWindow("plate");
  }

  vector<Rect> newSortedRect;
  newSortedRect.push_back(chineseRect);
  RebuildRect(sortedRect, newSortedRect, specIndex);

  if (newSortedRect.size() == 0) return 0x05;

  bool useSlideWindow = true;
  bool useAdapThreshold = true;
  //bool useAdapThreshold = CParams::instance()->getParam1b();

  for (size_t i = 0; i < newSortedRect.size(); i++) {
    Rect mr = newSortedRect[i];

    // Mat auxRoi(img_threshold, mr);
    Mat auxRoi(input_grey, mr);
    Mat newRoi;

    if (i == 0) {
      if (useSlideWindow) {
        float slideLengthRatio = 0.1f;
        //float slideLengthRatio = CParams::instance()->getParam1f();
        if (!slideChineseWindow(input_grey, mr, newRoi, plateType, slideLengthRatio, useAdapThreshold))
          judgeChinese(auxRoi, newRoi, plateType);
      }
      else
        judgeChinese(auxRoi, newRoi, plateType);
    }
    else {
      if (BLUE == plateType) {  
        threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY + CV_THRESH_OTSU);
      }
      else if (YELLOW == plateType) {
        threshold(auxRoi, newRoi, 0, 255, CV_THRESH_BINARY_INV + CV_THRESH_OTSU);
      }
      else if (WHITE == plateType) {
        threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY_INV);
      }
      else {
        threshold(auxRoi, newRoi, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
      }

      newRoi = preprocessChar(newRoi);
    }
     
    if (0) {
      if (i == 0) {
        imshow("input_grey", input_grey);
        waitKey(0);
        destroyWindow("input_grey");
      }
      if (i == 0) {
        imshow("newRoi", newRoi);
        waitKey(0);
        destroyWindow("newRoi");
      }
    }

    resultVec.push_back(newRoi);
  }

  return 0;
}
Ejemplo n.º 9
0
//Segment the chars from plate
vector<CharSegment> OCR::segment(Plate plate){
    Mat input=plate.plateImg;
    vector<CharSegment> output;

    //Threshold input image
    Mat img_threshold;
    //To make char image clearly
//    threshold(input, img_threshold, 60, 255, CV_THRESH_BINARY_INV);	//Spain
//    threshold(input, img_threshold, 150~160, 255, CV_THRESH_BINARY);	//China
    // TODO: IMPORTANT
    threshold(input, img_threshold, 175, 255, CV_THRESH_BINARY);	//China
    if(debug) {
        imshow("OCR_Threshold_Binary", img_threshold);
    }

    Mat img_contours;
    img_threshold.copyTo(img_contours);
    //Find contours of possibles characters
    vector< vector< Point> > contours;
    findContours(img_contours,
            contours, // a vector of contours
            CV_RETR_EXTERNAL, // retrieve the external contours
            CV_CHAIN_APPROX_NONE); // all pixels of each contours
    
    // Draw blue contours on a white image
    cv::Mat result;
    img_threshold.copyTo(result);
    cvtColor(result, result, CV_GRAY2RGB);
    cv::drawContours(result,
    		contours,
            -1, // draw all contours
            cv::Scalar(255,0,0), // in BLUE
            1); // with a thickness of 1

    //Start to iterate to each contour founded
    vector<vector<Point> >::iterator itc = contours.begin();
    //Remove patch that are no inside limits of aspect ratio and area.    
    while (itc!=contours.end()) {
        //Create bounding rect of object
        Rect mr = boundingRect(Mat(*itc));
        rectangle(result, mr, Scalar(0,255,0));	//Possible chars in GREEN

        //Crop image
        Mat auxRoi(img_threshold, mr);
        if(verifySizes(auxRoi)){
            auxRoi=preprocessChar(auxRoi);
            output.push_back(CharSegment(auxRoi, mr));
            rectangle(result, mr, Scalar(0,0,255));	//Possible chars in RED
        }
        ++itc;
    }

    if(debug)
    {
        cout << "OCR number of chars: " << output.size() << "\n";
        imshow("OCR Chars", result);
        cvWaitKey(0);
    }

    return output;
}