Мне нужно преобразовать некоторые изображения в двоичный файл для распознавания текста.
Вот функции, которые я использую:
Mat binarize(Mat & Img, Mat& res, float blocksize, bool inverse)
{
Img.convertTo(Img,CV_32FC1,1.0/255.0);
CalcBlockMeanVariance(Img,res, blocksize, inverse);
res=1.0-res;
res=Img+res;
if (inverse) {
cv::threshold(res,res,0.85,1,cv::THRESH_BINARY_INV);
} else {
cv::threshold(res,res,0.85,1,cv::THRESH_BINARY);
}
cv::resize(res,res,cv::Size(res.cols/2,res.rows/2));
return res;
}
куда CalcBlockMeanVariance
:
void CalcBlockMeanVariance(Mat& Img,Mat& Res,float blockSide, bool inverse) //21 blockSide - the parameter (set greater for larger font on image)
{
Mat I;
Img.convertTo(I,CV_32FC1);
Res=Mat::zeros(Img.rows/blockSide,Img.cols/blockSide,CV_32FC1);
Mat inpaintmask;
Mat patch;
Mat smallImg;
Scalar m,s;
for(int i=0;i<Img.rows-blockSide;i+=blockSide)
{
for (int j=0;j<Img.cols-blockSide;j+=blockSide)
{
patch=I(Range(i,i+blockSide+1),Range(j,j+blockSide+1));
cv::meanStdDev(patch,m,s);
if(s[0]>0.01) // Thresholding parameter (set smaller for lower contrast image)
{
Res.at<float>(i/blockSide,j/blockSide)=m[0];
}else
{
Res.at<float>(i/blockSide,j/blockSide)=0;
}
}
}
cv::resize(I,smallImg,Res.size());
if (inverse) {
cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY_INV);
} else {
cv::threshold(Res,inpaintmask,0.02,1.0,cv::THRESH_BINARY);
}Mat inpainted;
smallImg.convertTo(smallImg,CV_8UC1,255);
inpaintmask.convertTo(inpaintmask,CV_8UC1);
inpaint(smallImg, inpaintmask, inpainted, 5, INPAINT_TELEA);
cv::resize(inpainted,Res,Img.size());
Res.convertTo(Res,CV_32FC1,1.0/255.0);
}
При прохождении в 1
в CalcBlockMeanVariance
как blockSide
Я получаю этот результат, я пытался поднять blockSide
но это только приводит к худшим результатам.
До:
После:
Кто-нибудь может предложить другой метод для преобразования этого изображения в двоичный файл в качестве подготовки к распознаванию?
Благодарю.
Я думаю, что вы можете сделать свой порог, используя Оцу метод. Вы можете применить его ко всему изображению или к блокам изображения. Я сделал следующие шаги:
Otsu
метод на желаемом входе. Closing
результат.Код Python
image = cv2.imread('image4.png', cv2.IMREAD_GRAYSCALE) # reading image
if image is None:
print 'Can not find the image!'
exit(-1)
# thresholding image using ostu method
ret, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
# applying closing operation using ellipse kernel
N = 3
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (N, N))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# showing the result
cv2.imshow('thresh', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
объяснение
В первой части я прочитал входное изображение, используя imread
и проверил, что изображение открылось правильно !.
image = cv2.imread('image4.png', cv2.IMREAD_GRAYSCALE) # reading image
if image is None:
print 'Can not find the image!'
exit(-1)
Теперь установив изображение с помощью otsu
метод кормления thresh
метод с THRESH_BINARY_INV | THRESH_OTSU
в качестве аргумента. otsu
Метод работает на основе задачи оптимизации, находящей лучшее значение для порогового значения. Поэтому я указал диапазон возможных значений порогового значения, задав для него нижнюю границу: 0
и верхняя граница 255
,
ret, thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
И операция закрытия выполняется для удаления черных дыр в изображении с помощью Ellipse
ядро.
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (N, N))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
Результат