Note: I know that there's already an accepted answer, but I want to provide a more simple version.
Basically, first find the contours of every shape in the image (every cell) that has an area greater than a chosen number that will filter out any noise.
Loop through the contours, and find the smallest and greatest x and y coordinates. With the 4 points, we can save the pixels from the image within the four coordinates into a separate array, fill in the original image with white, and draw the table back onto the image.
The code:
import cv2
img = cv2.imread("table.png")
h, w, _ = img.shape
x1, y1 = w, h
x2, y2 = 0, 0
contours, _ = cv2.findContours(cv2.Canny(img, 0, 0), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) > 1000:
x1 = min(cnt[..., 0].min(), x1)
y1 = min(cnt[..., 1].min(), y1)
x2 = max(cnt[..., 0].max(), x2)
y2 = max(cnt[..., 1].max(), y2)
pad = 2
x1 -= pad
y1 -= pad
x2 += pad * 2
y2 += pad * 2
table = img[y1:y2, x1:x2].copy()
img.fill(255)
img[y1:y2, x1:x2] = table
cv2.imshow("lined_table.png", img)
cv2.waitKey(0)
Output:

Explanation:
- Import the opencv module and read in the image. Get the dimensions of the image and define temporary coordinates for the first corner of the table and the last corner of the table:
import cv2
img = cv2.imread("table.png")
h, w, _ = img.shape
x1, y1 = w, h
x2, y2 = 0, 0
- Get the contours of the image, and loop through each contour, filtering out the contours with an area of less than 1000:
contours, _ = cv2.findContours(cv2.Canny(img, 0, 0), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) > 999:
- Update the values of the coordinates of the first corner and last corner of the table:
x1 = min(cnt[..., 0].min(), x1)
y1 = min(cnt[..., 1].min(), y1)
x2 = max(cnt[..., 0].max(), x2)
y2 = max(cnt[..., 1].max(), y2)
- Apply a pad around each coordinate, depending on the width of the lines:
pad = 2
x1 -= pad
y1 -= pad
x2 += pad * 2
y2 += pad * 2
- Copy part of the image into a variable according to the found x and y coordinates, empty the image, and redraw the table onto the image. Finally, show the image:
table = img[y_1:y_2, x_1:x_2].copy()
img.fill(255)
img[y_1:y_2, x_1:x_2] = table
cv2.imwrite("lined_table.png", img)
cv2.waitKey(0)