i trying find way break split lines of text in scanned document has been adaptive thresholded. right now, storing pixel values of document unsigned ints 0 255, , taking average of pixels in each line, , split lines ranges based on whether average of pixels values larger 250, , take median of each range of lines holds. however, methods fails, there can black splotches on image.
is there more noise-resistant way task?
edit: here code. "warped" name of original image, "cuts" want split image.
warped = threshold_adaptive(warped, 250, offset = 10) warped = warped.astype("uint8") * 255 # areas can split image on whitespace make ocr more accurate color_level = np.array([np.sum(line) / len(line) line in warped]) cuts = [] = 0 while(i < len(color_level)): if color_level[i] > 250: begin = while(color_level[i] > 250): += 1 cuts.append((i + begin)/2) # middle of whitespace region else: += 1
from input image, need make text white, , background black
you need compute rotation angle of bill. simple approach find minarearect of white points (findnonzero), , get:
then can rotate bill, text horizontal:
now can compute horizontal projection (reduce). can take average value in each line. apply threshold th on histogram account noise in image (here used 0, i.e. no noise). lines background have value >0, text lines have value 0 in histogram. take average bin coordinate of each continuous sequence of white bins in histogram. y coordinate of lines:
here code. it's in c++, since of work opencv functions, should easy convertible python. @ least, can use reference:
#include <opencv2/opencv.hpp> using namespace cv; using namespace std; int main() { // read image mat3b img = imread("path_to_image"); // binarize image. text white, background black mat1b bin; cvtcolor(img, bin, color_bgr2gray); bin = bin < 200; // find white pixels vector<point> pts; findnonzero(bin, pts); // rotated rect of white pixels rotatedrect box = minarearect(pts); if (box.size.width > box.size.height) { swap(box.size.width, box.size.height); box.angle += 90.f; } point2f vertices[4]; box.points(vertices); (int = 0; < 4; ++i) { line(img, vertices[i], vertices[(i + 1) % 4], scalar(0, 255, 0)); } // rotate image according found angle mat1b rotated; mat m = getrotationmatrix2d(box.center, box.angle, 1.0); warpaffine(bin, rotated, m, bin.size()); // compute horizontal projections mat1f horproj; reduce(rotated, horproj, 1, cv_reduce_avg); // remove noise in histogram. white bins identify space lines, black bins identify text lines float th = 0; mat1b hist = horproj <= th; // mean coordinate of white white pixels groups vector<int> ycoords; int y = 0; int count = 0; bool isspace = false; (int = 0; < rotated.rows; ++i) { if (!isspace) { if (hist(i)) { isspace = true; count = 1; y = i; } } else { if (!hist(i)) { isspace = false; ycoords.push_back(y / count); } else { y += i; count++; } } } // draw line final result mat3b result; cvtcolor(rotated, result, color_gray2bgr); (int = 0; < ycoords.size(); ++i) { line(result, point(0, ycoords[i]), point(result.cols, ycoords[i]), scalar(0, 255, 0)); } return 0; } 




Comments
Post a Comment