3

I need a way to split up the header and blueprint part of an image, but right now i'm out of ideas on how to do this. (cant use the original image so i tried to recreate it) document

I've tried to do this using opencv's houghlines but it detects a lot of different lines because of the blueprint so i cant find a clear spot to cut off the image.

(like this:) document with lines

What i need is 2 different images of the header and the blueprint, but right now i can't find a good way to do this so any help would be appreciated.

NielsNL4
  • 580
  • 1
  • 8
  • 21

2 Answers2

2

For your given input image :

input

If I use the following piece of code :

import cv2
import numpy as np
img = cv2.imread('test1.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))
    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
cv2.imwrite('houghlines3.jpg',img)

I get the following output :

output

See there is only one big straight line which differentiates the header and the blueprint part. You can get the starting and ending y co-ordinate of this line if you just print y1 and y2. For this case, they are y1 : 140, y2 : 141. Now what you need, is just crop the picture up to y pixel 141 value like this :

img = cv2.imread(path/to/original/image)
img_header = img[:141,:]
img_blueprint = img[141:, :]
cv2.imwrite("header.png", img_header)
cv2.imwrite("blueprint.png", img_blueprint)

Now, come to your problem. Here is a possible way. See the biggest straight line differentiating the header and the blueprint has got detected by three different red straight lines through the houghline transform. For these three lines, the starting y co-ordinates will be very much close like for example say 142, 145, 143. You need to append all ending y co-ordinates of the straight lines (y2) in a list and cluster all of them based on adjacency with a threshold value of 5-10 pixels, take the biggest cluster, take the largest ending y co-ordinate from the cluster and crop the original image accordingly.

Arkistarvh Kltzuonstev
  • 6,824
  • 7
  • 26
  • 56
1

If the line separating the header from the content is the longest black line across the width of the image, you can find it by summing the pixels across each row and then finding which row adds up to the least, i.e. has most black pixels:

# get sums across rows
rowSums = np.sum(image,axis=1)

# get index of blackest row
longestBlack = np.argmin(rowSums)
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Could elaborate on your solution; it seems simple and would work in my case. Let's say I have a pdf document that has multiple long lines separating its paragraphs, how would I split this document into sequential images based on these long lines? – Akbar Hussein Oct 13 '21 at 05:03
  • @AkbarHussein I'm not sure what's to add. Load the image, sum the pixels up across the rows, find the row(s) that add up to the least as they will be blackest - black pixels being zero. Rows with lots of white pixels will add up to larger totals - white pixels each contributing 255 to the sum. Diagram here https://stackoverflow.com/a/63174271/2836621 – Mark Setchell Oct 13 '21 at 05:56
  • My knowledge of NumPy is limited; I'd appreciate it if you could direct me to a post or a GitHub repository dealing with that problem. There is a piece of software called krop; it works only on Linux; if I could I want to replicate some of its functions in python! http://arminstraub.com/software/krop – Akbar Hussein Oct 13 '21 at 07:33