Hello, I am trying to setup an automated way to get the date from coins. I am keeping it simple and decided to first try it on pennies since the dates are in the same location in relation to its circle. I am using tesseract for the OCR of the date. I am having difficulty processing the date from the penny so that tesseract will correctly translate it.
My question is, does anyone have a good idea what I can do to the image from a penny's date field so that tesseract will translate correctly. I am trying morphologies but can't get the right setting so that it works.
Here is my code(needs alot of cleanup but does the job)
include "opencv2/highgui/highgui.hpp"
include "opencv2/imgproc/imgproc.hpp"
include "tesseract/baseapi.h"
include "iostream"
using namespace cv; using namespace std;
static void help() { cout << "\nThis program demonstrates circle finding with the Hough transform.\n" "Usage:\n" "./houghcircles <image_name>, Default is pic1.png\n" << endl; }
/** * Rotate an image */ void rotate(cv::Mat& src, double angle, cv::Mat& dst) { int len = std::max(src.cols, src.rows); cv::Point2f pt(len/2., len/2.); cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);
cv::warpAffine(src, dst, r, cv::Size(len, len));
}
int main(int argc, char* argv) { const char filename = argc >= 2 ? argv[1] : "board.jpg";
int centerx,centery, radius;
//Mat img = imread(filename, 0);
Mat img = imread(filename,0);
Mat org;
img.copyTo(org);
Mat date_img;
if(img.empty())
{
help();
cout << "can not open " << filename << endl;
return -1;
}
Mat cimg;
medianBlur(img, img, 5);
cvtColor(img, cimg, COLOR_GRAY2BGR);
vector<Vec3f> circles;
HoughCircles(img, circles, HOUGH_GRADIENT, 1, 300,
100, 30, 400, 2000 // change the last two parameters
// (min_radius & max_radius) to detect larger circles
);
for( size_t i = 0; i < circles.size(); i++ )
{
Vec3i c = circles[i];
circle( cimg, Point(c[0], c[1]), c[2], Scalar(0,255,255), 3, LINE_AA);
circle( cimg, Point(c[0], c[1]), 2, Scalar(0,255,0), 3, LINE_AA);
centerx = c[0];
centery = c[1];
radius = c[2];
cv::Mat mask = cv::Mat::zeros( img.rows, img.cols, CV_8UC1 );
circle( mask, Point(c[0], c[1]), c[2], Scalar(255,255,255), -1, 8, 0 ); //-1 means filled
org.copyTo( cimg, mask ); // copy values of img to dst if mask is > 0.
break;
}
//cv::Mat roi( cimg, cv::Rect( centerx-radius, centery-radius, radius*2, radius*2 ) );
cout << "DIAMETER: " << radius << " CENTERX: " << centerx << " CENTERY: " << centery << endl;
cv::Rect myROI(centerx-radius, centery-radius, radius*2,radius*2);
cimg = cimg(myROI);
// rotate(cimg, 90, cimg);
// rectangle(cimg, Point(cimg.rows/1.45, cimg.cols/1.6),Point(cimg.rows/1.1,cimg.cols/1.35), Scalar(0,255,255), 3, 8, 0 );
//get date
date_img = cimg(Rect( Point(cimg.rows/1.45, cimg.cols/1.6),Point(cimg.rows/1.1,cimg.cols/1.35) ) ) ;
date_img.convertTo(date_img, -1, 1.8, 1);
Mat element = getStructuringElement(MORPH_ELLIPSE, Size(15,15), Point(-1,-1) );
erode(date_img,date_img, element);
//dilate(date_img, date_img, element);
morphologyEx(date_img, date_img, MORPH_CLOSE, element);
// medianBlur(date_img, date_img, 7);
// Pass it to Tesseract API
tesseract::TessBaseAPI tess;
tess.Init(NULL, "eng", tesseract::OEM_DEFAULT);
tess.SetPageSegMode(tesseract::PSM_SINGLE_BLOCK);
tess.SetImage((uchar*)date_img.data, date_img.cols, date_img.rows, 1, date_img.cols);
// Get the text
char* out = tess.GetUTF8Text();
std::cout << "DATE: " << out << std::endl;
// imshow("detected circles", cimg); // imshow("dates", date_img); // waitKey();
imwrite("date_img.jpg", date_img);
return 0;
}
You can compile like this:
g++ getDateOCR.cpp -o OCRDATE `pkg-config --cflags --libs opencv tesseract`
And run like this:
./OCRDATE 1920-penny.png
You can use this penny image to test:
http://coinmatico.com/wp-content/uploads/2014/05/1920-penny-1024x973.png