我正在使用opencv编写程序来进行文本检测和提取。 我使用Sobel衍生物进行边缘检测并得到以下结果:
但我希望得到以下结果:
(我为模糊图像道歉。)
我遇到的问题是边缘内部的“空白区域”“混淆”我正在使用的算法,所以当算法检测到“空白部分”在线条本身的两条线之间分开时会感到困惑并开始碰到信件本身而不是两条线之间的保持。我相信这个错误可以通过实现第二个结果来解决。
任何人都知道我需要做出哪些改变?在这个导数中?也许使用不同的衍生物?
代码:
Mat ProfileSeamTextLineExtractor::computeDerivative(){
Mat img = _image;
Mat gradiant_mat;
int scale = 2;
int delta = 0;
int ddepth = CV_16S;
GaussianBlur(img, img, Size(3, 3), 0, 0, BORDER_DEFAULT);
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
Sobel(img, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_x, abs_grad_x);
Sobel(img, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
convertScaleAbs(grad_y, abs_grad_y);
/// Total Gradient (approximate)
addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, gradiant_mat);
return gradiant_mat;
}
此致
答案 0 :(得分:0)
我真的不明白你的最终目标是什么。你最终想要一个很好的填写版本的文字,以便你可以识别字符?如果你正在寻找的话,我可以试一试。
这是我在尝试移除内孔时所做的: Holes removal attempted http://i60.tinypic.com/fn5nhd.jpg
对于这个我没有打扰: No holes removed http://i62.tinypic.com/14j0pzk.jpg
在文本被切断的边缘处失败。
显然,我必须处理已经经过一些处理的图像。如果我有原版并产生更好的输出,我或许可以给你更多的帮助。如果背景足够干净,你可能根本不需要使用衍生物。
以下是代码:
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void printInnerContours (int contourPos, Mat &filled, vector<vector<Point2i > > &contours, vector<Vec4i> &hierarchy, int area);
int main() {
int areaThresh;
vector<vector<Point2i > > contours;
vector<Vec4i> hierarchy;
Mat text = imread ("../wHWHA.jpg", 0); //write greyscale
threshold (text, text, 50, 255, THRESH_BINARY);
imwrite ("../text1.jpg", text);
areaThresh = (0.01 * text.rows * text.cols) / 100;
findContours (text, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
Mat filled = Mat::zeros(text.rows, text.cols, CV_8U);
cout << contours.size() << endl;
for (int i = 0; i < contours.size(); i++) {
int area = contourArea(contours[i]);
if (area > areaThresh) {
if ((hierarchy[i][2] != -1) && (hierarchy[i][3] == -1)) {
drawContours (filled, contours, i, 255, -1);
if (hierarchy[i][2] != -1) {
printInnerContours (hierarchy[i][2], filled, contours, hierarchy, area);
}
}
}
}
imwrite("../output.jpg", filled);
return 0;
}
void printInnerContours (int contourPos, Mat &filled, vector<vector<Point2i > > &contours, vector<Vec4i> &hierarchy, int area) {
int areaFrac = 5;
if (((contourArea (contours[contourPos]) * 100) / area) < areaFrac) {
//drawContours (filled, contours, contourPos, 0, -1);
}
if (hierarchy[contourPos][2] != -1) {
printInnerContours (hierarchy[contourPos][2], filled, contours, hierarchy, area);
}
if (hierarchy[contourPos][0] != -1) {
printInnerContours (hierarchy[contourPos][0], filled, contours, hierarchy, area);
}
}
答案 1 :(得分:0)
尝试使用第二个sobel导数,添加,规范化(这可能与addWeighted相同),然后以最佳方式进行阈值处理。我的结果与您的结果相似,具有不同的阈值。
以下是一个例子:
cv::Mat result;
cvtColor(image, gray, CV_BGR2GRAY);
cv::medianBlur(gray, gray, 3);
cv::Mat sobel_x, sobel_y, result;
cv::Sobel(gray, sobel_x, CV_32FC1, 2, 0, 5);
cv::Sobel(gray, sobel_y, CV_32FC1, 0, 2, 5);
cv::Mat sum = sobel_x + sobel_y;
cv::normalize(sum, result, 0, 255, CV_MINMAX, CV_8UC1);
//Determine optimal threshold value using THRESH_OTSU.
// This didn't give me optimal results, but was a good starting point.
cv::Mat temp, final;
double threshold = cv::threshold(result, temp, 0, 255, CV_THRESH_BINARY+CV_THRESH_OTSU);
cv::threshold(result, final, threshold*.9, 255, CV_THRESH_BINARY);
我能够清晰地提取深色背景上的浅色文字和浅色背景上的深色文字。
如果您需要最终图像始终为带黑色文本的白色背景,则可以执行以下操作:
cv::Scalar avgPixelIntensity = cv::mean( final );
if(avgPixelIntensity[0] < 127.0)
cv::bitwise_not(final, final);
我尝试了很多不同的文本提取方法,找不到任何可行的方法,但这似乎是。这需要花费大量的试验和错误来解决,所以我希望这会有所帮助。