问题描述
我正在尝试使用opencv(Python)从填写的表单中删除方形框(垂直线和水平线).我正在尝试通过OpenCV的形态学检测垂直和水平线.
I'm trying to remove the square boxes(vertical and horizontal lines) from a filled out form using opencv (Python). I am trying to detect the vertical and horizontal lines through morphological operations of OpenCV.
检测到垂直线和水平线后.
After detecting the Vertical and Horizontal lines.
垂直线
检测到水平线和垂直线后,我只是将它们相加并从处理后的图像中减去它.res = verticle_lines_img + horizontal_lines_img
exp = img_bin - res
After the horizontal and vertical lines are detected , i am simply adding them and subtracting it from processed image.res = verticle_lines_img + horizontal_lines_img
exp = img_bin - res
最终结果没有达到预期的平滑.
The final results is not so smoothed as expected.
完整的代码是
# Read the image
img_for_box_extraction_path='aligned_filled.jpg'
img = cv2.imread(img_for_box_extraction_path, 0)
# Thresholding the image
(thresh, img_bin) = cv2.threshold(img, 128, 255,cv2.THRESH_BINARY|
cv2.THRESH_OTSU)
# Invert the image
img_bin = ~img_bin
cv2.imwrite("Image_bin.jpg",img_bin)
bw = cv2.adaptiveThreshold(img_bin, 255, cv2.ADAPTIVE_THRESH_MEAN_C, \
cv2.THRESH_BINARY, 15, -2)
horizontal = np.copy(bw)
vertical = np.copy(bw)
# Defining a kernel length for horizontal and vertical
cols = horizontal.shape[1]
horizontal_size = int(cols)
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT,
(horizontal_size, 1))
# Apply morphology operations
horizontal = cv2.erode(horizontal, horizontalStructure)
horizontal = cv2.dilate(horizontal, horizontalStructure)
rows = vertical.shape[0]
verticalsize = int(rows)
# Create structure element for extracting vertical lines through morphology
operations
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1,
verticalsize))
# Apply morphology operations
vertical = cv2.erode(vertical, verticalStructure)
vertical = cv2.dilate(vertical, verticalStructure)
#kernel_length = np.array(img).shape[1]//80
#kernel_length = 7
# A verticle kernel of (1 X kernel_length =6), which will detect all the
verticle lines from the image.
verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 6))
# A horizontal kernel of (kernel_length=7 X 1), which will help to detect
all the horizontal line from the image.
hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 1))
# A kernel of (3 X 3) ones.
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# Morphological operation to detect vertical lines from an image
img_temp1 = cv2.erode(img_bin, verticle_kernel, iterations=3)
verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=2)
cv2.imwrite("verticle_lines.jpg",verticle_lines_img)
# Morphological operation to detect horizontal lines from an image
img_temp2 = cv2.erode(img_bin, hori_kernel, iterations=3)
horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=2)
cv2.imwrite("horizontal_lines.jpg",verticle_lines_img)
res = verticle_lines_img + horizontal_lines_img
#fin = cv2.bitwise_and(img_bin, img_bin, mask = cv2.bitwise_not(res))
exp = img_bin - res
exp = ~exp
cv2.imwrite("final.jpg",exp)
什么是检测和删除方形框的新颖方法?
What could be a novel way to detect and remove the square boxes?
推荐答案
网格线比文本细,所以我建议以下内容:
The grid lines are thinner than the text, so I suggest the following:
阈值->侵蚀-> 去除小斑点->扩张
threshold->erode->remove small blobs->dilate
这是上述方法的结果:
Here is the result of the above described method:
我一直以错误的语言提供示例代码感到很遗憾,但这就是C ++生成结果的原因.我认为函数调用在python中应该非常相似.关于Blob的注释特别要删除(如何使用OpenCV )这个家伙是用python做到的,而且比我的还干净WAAAY,所以我建议您参考一下以删除您的小斑点.我删除了小于15像素的任何东西,这是我任意尝试的第一件事.我可能已经杀死了一些字符(没有检查),并且限制很高,所以您将想要找到适合自己目的的值.
I feel bad to keep providing example code in the wrong language, but here is what generated that result in C++. I think the function calls should be pretty similar in python. A note on the blob remove in particular (How to remove small connected objects using OpenCV) this guy does it in python and it is WAAAY cleaner than mine, so I suggest you reference that to remove your small blobs. I removed anything less than 15 px which was super arbitrary and first thing i tried. I may have killed some characters (didn't check) with that high of a limit, so you will want to find the right value for your purposes.
int main(int argc, char** argv)
{
Mat image = imread("../../resources/images/fullForm.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat thresholded, errodedImage, openedImage;
threshold(image, thresholded, 200, 255, THRESH_BINARY_INV);
//errode first
erode(thresholded, errodedImage, getStructuringElement(MORPH_CROSS, Size(3, 3)), cv::Point(-1, -1), 1);
//delete any blobs with less than 15 px
Mat labels, stats, centroids;
Mat deblobbedImage = errodedImage.clone();
int nccomps = connectedComponentsWithStats(errodedImage, labels, stats, centroids);
std::vector<int> smallBlobs = std::vector<int>();
for (int i = 0; i < nccomps; i++)
{
if (stats.at<int>(i, CC_STAT_AREA) < 15)
{
smallBlobs.push_back(0);
}
else
{
smallBlobs.push_back(1);
}
}
for (int y = 0; y < errodedImage.rows; y++)
{
for (int x = 0; x < errodedImage.cols; x++)
{
int label = labels.at<int>(y, x);
CV_Assert(0 <= label && label <= nccomps);
if (smallBlobs[label] == 0)
{
deblobbedImage.at<uchar>(y, x) = 0;
}
}
}
//dilate to restore text
dilate(deblobbedImage, openedImage, getStructuringElement(MORPH_CROSS, Size(3, 3)), cv::Point(-1, -1), 1);
imshow("source", image);
imshow("Thresholded", thresholded);
imshow("erroded", errodedImage);
imshow("deblobbed", deblobbedImage);
imshow("finished", openedImage);
waitKey(0);
return 0;
}
这篇关于在OpenCV中检测和删除垂直和水平线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!