を:ここ
![Example W2](https://i.stack.imgur.com/sdtGD.png)
私はOpenCVの2または3とするかどうかを使用することができるPythonコードと共に、これまでに試みたものの結果でありますあなたが私のコードの中で何かを従わないと私に教えてください。この概念の最大の障害は、
1以下のとおりです。(あなたは別の塊にそれを壊すメインボックスラインで騒々しいブレークを持っている場合)
2:これは手書きのテキストが存在することができるものであればIDKのしかし、文字を持つとボックスの端が重なってしまうことがあります。
3:姿勢チェックは絶対にありません(実際にはこれを改善したいと思うかもしれませんが、それはあまりにも悪くなく、より正確なハンドルを与えるでしょう)。私は、あなたのボックスがxy軸にほぼ揃っているかどうか、それらが十分に歪んでいる場合、すべてのボックスコーナーにグロスオフセットを与えます(ただしそれらはまだすべて見つける必要があります)。
I fiddledすべてのテキストがエッジから分離されるようにしきい値設定ポイントを少し設定すると、必要に応じてメインラインを破る前にそれをさらに下げることができます。また、改行が心配な場合は、最終的な画像に十分大きな塊を追加することもできます。 ![Processing steps](https://i.stack.imgur.com/N6QMH.png)
![Final result](https://i.stack.imgur.com/auys9.jpg)
基本的に
、最も安定した(まだ接続箱を保つ可能性が最も低い値)でそれを得るために、閾値をいじるの最初のステップのボックスからテキストやノイズを分離するためのcuttoff値。
2番目に大きい正のBLOBを見つける(ボックスグリッドにする必要があります)。あなたのボックスがすべて一緒にいなければ、最高のブロブをいくつか取りたいかもしれませんが、それは粘着性になりますが、単一のブロブとして得ることができるように閾値を取得しようとします。
最後のステップでは、これを行うために、矩形を取得することです(最初の外側領域を無視して)負のブロブを探します。
そしてここでのコードは、(それはC++であることを申し訳ありませんが、うまくいけば、あなたが概念を理解し、とにかくそれを自分で書きます)です:
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <stdio.h>
#include <opencv2/opencv.hpp>
using namespace cv;
//Attempts to find the largest connected group of points (assumed to be the interconnected boundaries of the textbox grid)
Mat biggestComponent(Mat targetImage, int connectivity=8)
{
Mat inputImage;
inputImage = targetImage.clone();
Mat finalImage;// = inputImage;
int greatestBlobSize=0;
std::cout<<"Top"<<std::endl;
std::cout<<inputImage.rows<<std::endl;
std::cout<<inputImage.cols<<std::endl;
for(int i=0;i<inputImage.cols;i++)
{
for(int ii=0;ii<inputImage.rows;ii++)
{
if(inputImage.at<uchar>(ii,i)!=0)
{
Mat lastImage;
lastImage = inputImage.clone();
Rect* boundbox;
int blobSize = floodFill(inputImage, cv::Point(i,ii), Scalar(0),boundbox,Scalar(200),Scalar(255),connectivity);
if(greatestBlobSize<blobSize)
{
greatestBlobSize=blobSize;
std::cout<<blobSize<<std::endl;
Mat tempDif = lastImage-inputImage;
finalImage = tempDif.clone();
}
//std::cout<<"Loop"<<std::endl;
}
}
}
return finalImage;
}
//Takes an image that only has outlines of boxes and gets handles for each textbox.
//Returns a vector of points which represent the top left corners of the text boxes.
std::vector<Rect> boxCorners(Mat processedImage, int connectivity=4)
{
std::vector<Rect> boxHandles;
Mat inputImage;
bool outerRegionFlag=true;
inputImage = processedImage.clone();
std::cout<<inputImage.rows<<std::endl;
std::cout<<inputImage.cols<<std::endl;
for(int i=0;i<inputImage.cols;i++)
{
for(int ii=0;ii<inputImage.rows;ii++)
{
if(inputImage.at<uchar>(ii,i)==0)
{
Mat lastImage;
lastImage = inputImage.clone();
Rect boundBox;
if(outerRegionFlag) //This is to floodfill the outer zone of the page
{
outerRegionFlag=false;
floodFill(inputImage, cv::Point(i,ii), Scalar(255),&boundBox,Scalar(0),Scalar(50),connectivity);
}
else
{
floodFill(inputImage, cv::Point(i,ii), Scalar(255),&boundBox,Scalar(0),Scalar(50),connectivity);
boxHandles.push_back(boundBox);
}
}
}
}
return boxHandles;
}
Mat drawTestBoxes(Mat originalImage, std::vector<Rect> boxes)
{
Mat outImage;
outImage = originalImage.clone();
outImage = outImage*0; //really I am just being lazy, this should just be initialized with dimensions
for(int i=0;i<boxes.size();i++)
{
rectangle(outImage,boxes[i],Scalar(255));
}
return outImage;
}
int main() {
Mat image;
Mat thresholded;
Mat processed;
image = imread("Images/W2.png", 1);
Mat channel[3];
split(image, channel);
threshold(channel[0],thresholded,150,255,1);
std::cout<<"Coputing biggest object"<<std::endl;
processed = biggestComponent(thresholded);
std::vector<Rect> textBoxes = boxCorners(processed);
Mat finalBoxes = drawTestBoxes(image,textBoxes);
namedWindow("Original", WINDOW_AUTOSIZE);
imshow("Original", channel[0]);
namedWindow("Thresholded", WINDOW_AUTOSIZE);
imshow("Thresholded", thresholded);
namedWindow("Processed", WINDOW_AUTOSIZE);
imshow("Processed", processed);
namedWindow("Boxes", WINDOW_AUTOSIZE);
imshow("Boxes", finalBoxes);
std::cout<<"waiting for user input"<<std::endl;
waitKey(0);
return 0;
}
問題はこれとこれは垂直線はほとんど検出されないパラメータことで、 '' lines_v = cv2.HoughLinesP(エッジ、1、np.pi、100、minLineLength、maxLineGap)と垂直線を見つけることを試みますこれのために別のループを作ってください。 'HoughLinesP'関数のための異なるパラメータ値を試してください。水平線と垂直線に対して異なる値を設定してください。 – ebeneditos