// Copy the given image rectangle to Tesseract, with adaptive thresholding // if the image is not already binary. void TessBaseAPI::CopyImageToTesseract(const unsigned char* imagedata, int bytes_per_pixel, int bytes_per_line, int left, int top, int width, int height) { if (bytes_per_pixel > 0) { // Threshold grey or color. int* thresholds = new int[bytes_per_pixel]; int* hi_values = new int[bytes_per_pixel]; // Compute the thresholds. OtsuThreshold(imagedata, bytes_per_pixel, bytes_per_line, left, top, left + width, top + height, thresholds, hi_values); // Threshold the image to the tesseract global page_image. ThresholdRect(imagedata, bytes_per_pixel, bytes_per_line, left, top, width, height, thresholds, hi_values); delete [] thresholds; delete [] hi_values; } else { CopyBinaryRect(imagedata, bytes_per_line, left, top, width, height); } }
uint Histogram::OtsuThreshold(Image& Source) { uint Histogram[256]; Histogram1C(Source, Histogram); return OtsuThreshold(Histogram, Source.Width() * Source.Height()); }
// Otsu threshold the rectangle, taking everything except the image buffer // pointer from the class, to the output Pix. void ImageThresholder::OtsuThresholdRectToPix(const unsigned char* imagedata, int bytes_per_pixel, int bytes_per_line, Pix** pix) const { int* thresholds; int* hi_values; OtsuThreshold(imagedata, bytes_per_pixel, bytes_per_line, rect_left_, rect_top_, rect_width_, rect_height_, &thresholds, &hi_values); // Threshold the image to the given IMAGE. ThresholdRectToPix(imagedata, bytes_per_pixel, bytes_per_line, thresholds, hi_values, pix); delete [] thresholds; delete [] hi_values; }
int _tmain(int argc, _TCHAR* argv[]) { //CvCapture *capture = cvCaptureFromCAM(0); int t = 10, n=0; double time = 0; while(1) { clock_t begin=clock(); //------------------------ Original Camera Feed -----------------------------------------// //IplImage *img = cvQueryFrame(capture); IplImage *img = cvLoadImage("../../Data/13 Oct/img13.jpg"); //cvNamedWindow("Camera Feed", 0); //cvShowImage("Camera Feed", img); //------------------------ Finding Gray Scale Image -------------------------------------// IplImage *gray = cvCreateImage(cvGetSize(img), 8, 1); cvCvtColor(img, gray, CV_BGR2GRAY); //cvReleaseImage(&img); //------------------------ Removing Salt and Pepper Noise -------------------------------// //cvSmooth(gray, gray, CV_MEDIAN, 3, 3, 0.0, 0.0); // For really poor images cvMorphologyEx(gray, gray, NULL, NULL, CV_MOP_OPEN, 1); // Removes Salt Noise for(int y = 0; y < gray->height; y++){ uchar* ptr = (uchar*) (gray->imageData + y * gray->widthStep); //implement inversion and pepper removal in single pass for(int x = 0; x < gray->width; x++) ptr[x] = 255-ptr[x]; // Pepper becomes Salt } cvMorphologyEx(gray, gray, NULL, NULL, CV_MOP_OPEN, 1); // Removes Pepper Noise //------------------------ Finding Gradient Image ---------------------------------------// int **A = (int **) calloc(gray->height, sizeof(int)); IplImage *gradient = cvCreateImage(cvGetSize(gray), 8, 1); float min=255, max=0; for(int i=1; i<gray->height-1; i++) { A[i] = (int*) calloc(gray->width, sizeof(int)); uchar* ptr1 = (uchar*) (gray->imageData + (i-1)*gray->widthStep); uchar* ptr2 = (uchar*) (gray->imageData + i*gray->widthStep); uchar* ptr3 = (uchar*) (gray->imageData + (i+1)*gray->widthStep); uchar* ptr = (uchar*) (gradient->imageData + i*gradient->widthStep); for(int j=1; j<gray->width-1; j++) { A[i][j] = (int)ptr1[j] + (int)ptr2[j-1] + (int)(-4)*ptr2[j] + (int)ptr2[j+1] + (int)ptr3[j]; if(A[i][j] <= min) min = (int)A[i][j]; if(A[i][j] >= max) max = (int)A[i][j]; } } //printf("max:%f min:%f\n", max, min); int *bins = (int *)calloc(256, sizeof(int)); for(int i=0; i<256; i++) bins[i] = 0; for(int i=1; i<gradient->height-1; i++) { uchar* ptr = (uchar*) (gradient->imageData + i*gradient->widthStep); for(int j=1; j<gradient->width-1; j++) { ptr[j] = (int)(A[i][j]-min)/(max-min)*255; bins[ptr[j]]++; } free(A[i]); } free(A); //------------ Applying 90 Percentile Threshold to get a Laplacian Edge Mask ------------// float sum=0; int pth=255; float percentile = 10; while((pth >= 0)&&(sum < gradient->imageSize*percentile/100)) sum += bins[pth--]; //printf("Percentile Threshold:%d\n", pth); //--------------- Applying the Laplacian Edge Mask to Original Gray Image ---------------// for(int i=0; i<256; i++) bins[i] = 0; for(int y = 0; y < gray->height; y++){ uchar* ptr = (uchar*) (gray->imageData + y * gray->widthStep); uchar* ptr1 = (uchar*) (gradient->imageData + y * gradient->widthStep); for(int x = 0; x < gray->width; x++){ if(ptr1[x] > pth){ bins[ptr[x]]++; } } } cvReleaseImage(&gradient); //cvReleaseImage(&gray); //------------- Thresholding the Original Gray Image using The Otsu Threshold -----------// int threshold = 255-OtsuThreshold(bins, 256); free(bins); //------------- Filtering points to get better line fittings ----------------------------// //img = cvQueryFrame(capture); //img = cvLoadImage("../../Data/13 Oct/img4.jpg"); //IplImage *otsu = cvCreateImage(cvGetSize(img), 8, 1); cvCvtColor(img, gray, CV_BGR2GRAY); //cvReleaseImage(&img); for(int i=0, d=t; i<gray->height; i++) { int flag = 0; uchar* ptr = (uchar*) (gray->imageData + i*gray->widthStep); for(int j=0; j<gray->width; j++) if(ptr[j] > threshold) ptr[j] = 255; else ptr[j] = 0; for(int x = 0; x < gray->width; x++) if(ptr[x]==255) { for(int i=0; i<d; i++) ptr[x+i] = 0; ptr[x+d/2] = 255; break; } } //---------------------------------- Hough Lines ----------------------------------------// CvMemStorage* line_storage = cvCreateMemStorage(0); CvSeq* results = cvHoughLines2(gray, line_storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 40, 5, 200); cvReleaseImage(&gray); printf("lines:%d\tt=%d\n", results->total, t); float angle = 0.0, temp; for(int i = 0; i < results->total; i++) { CvPoint* line = (CvPoint*)cvGetSeqElem(results, i); //cvLine(img, line[0], line[1], CV_RGB(255,0,0), 3, CV_AA, 0); if(line[0].y > line[1].y) temp = atan((line[0].y - line[1].y + 0.0) / (line[0].x - line[1].x)); else temp = atan((line[1].y - line[0].y + 0.0) / (line[1].x - line[0].x)); if(temp < 0) angle += 90 + 180/3.14*temp; else angle += 180/3.14*temp - 90; } printf("angle: %f\n", angle = angle/results->total); cvReleaseMemStorage(&line_storage); //cvNamedWindow("Hough Lines", 0); //cvShowImage("Hough Lines", img); send(FORWARD, angle); clock_t end=clock(); time = diffclock(end,begin); printf("Time Taken: %f fps\n", 1000/(time)); int c = cvWaitKey(0); if(c=='a') t++; else if(c == 'z') t--; else if(c == 'x') { send(BRAKE, 0); break; } } int c = cvWaitKey(0); return 0; }