Please Help Me !. the code below was organized according to jupyter notebook please rewrite a code which suits for pycharm.Also can you change it not to read specific words just scan what is what. in the table some cells have lines somes doesn't as you see see despite that for every floating number or word will correspond an excel cell . Or you can create a new code which converts this input data to csv file .Most thanks! İnput image michael_jordan_stats Code: from sklearn.cluster import AgglomerativeClustering from pytesseract import Output from tabulate import tabulate import pandas as pd import numpy as np import pytesseract import argparse import imutils import cv2 pytesseract.pytesseract.tesseract_cmd = 'C:\\Users\\AppData\\Local\\Programs\\Tesseract-OCR\\tesseract.exe' # construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image to be OCR'd") ap.add_argument("-o", "--output", required=True, help="path to output CSV file") ap.add_argument("-c", "--min-conf", type=int, default=0, help="minimum confidence value to filter weak text detection") ap.add_argument("-d", "--dist-thresh", type=float, default=25.0, help="distance threshold cutoff for clustering") ap.add_argument("-s", "--min-size", type=int, default=2, help="minimum cluster size (i.e., # of entries in column)") args = vars(ap.parse_args()) # set a seed for our random number generator np.random.seed(42) # load the input image and convert it to grayscale image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # initialize a rectangular kernel that is ~5x wider than it is tall, # then smooth the image using a 3x3 Gaussian blur and then apply a # blackhat morpholigical operator to find dark regions on a light # background kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (51, 11)) gray = cv2.GaussianBlur(gray, (3, 3), 0) blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, kernel) # compute the Scharr gradient of the blackhat image and scale the # result into the range [0, 255] grad = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1) grad = np.absolute(grad) (minVal, maxVal) = (np.min(grad), np.max(grad)) grad = (grad - minVal) / (maxVal - minVal) grad = (grad * 255).astype("uint8") # apply a closing operation using the rectangular kernel to close # gaps in between characters, apply Otsu's thresholding method, and # finally a dilation operation to enlarge foreground regions grad = cv2.morphologyEx(grad, cv2.MORPH_CLOSE, kernel) thresh = cv2.threshold(grad, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] thresh = cv2.dilate(thresh, None, iterations=3) cv2.imshow("Thresh", thresh) # find contours in the thresholded image and grab the largest one, # which we will assume is the stats table cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) tableCnt = max(cnts, key=cv2.contourArea) # compute the bounding box coordinates of the stats table and extract # the table from the input image (x, y, w, h) = cv2.boundingRect(tableCnt) table = image[y:y + h, x:x + w] # show the original input image and extracted table to our screen cv2.imshow("Input", image) cv2.imshow("Table", table) # set the PSM mode to detect sparse text, and then localize text in # the table options = "--psm 6" results = pytesseract.image_to_data( cv2.cvtColor(table, cv2.COLOR_BGR2RGB), config=options, output_type=Output.DICT) # initialize a list to store the (x, y)-coordinates of the detected # text along with the OCR'd text itself coords = [] ocrText = [] # loop over each of the individual text localizations for i in range(0, len(results["text"])): # extract the bounding box coordinates of the text region from # the current result x = results["left"] y = results["top"] w = results["width"] h = results["height"] # extract the OCR text itself along with the confidence of the # text localization text = results["text"] conf = int(results["conf"]) # filter out weak confidence text localizations if conf > args["min_conf"]: # update our text bounding box coordinates and OCR'd text, # respectively coords.append((x, y, w, h)) ocrText.append(text) # extract all x-coordinates from the text bounding boxes, setting the # y-coordinate value to zero xCoords = [(c[0], 0) for c in coords] # apply hierarchical agglomerative clustering to the coordinates clustering = AgglomerativeClustering( n_clusters=None, affinity="manhattan", linkage="complete", distance_threshold=args["dist_thresh"]) clustering.fit(xCoords) # initialize our list of sorted clusters sortedClusters = [] # loop over all clusters for l in np.unique(clustering.labels_): # extract the indexes for the coordinates belonging to the # current cluster idxs = np.where(clustering.labels_ == l)[0] # verify that the cluster is sufficiently large if len(idxs) > args["min_size"]: # compute the average x-coordinate value of the cluster and # update our clusters list with the current label and the # average x-coordinate avg = np.average([coords[0] for i in idxs]) sortedClusters.append((l, avg)) # sort the clusters by their average x-coordinate and initialize our # data frame sortedClusters.sort(key=lambda x: x[1]) df = pd.DataFrame() # loop over the clusters again, this time in sorted order for (l, _) in sortedClusters: # extract the indexes for the coordinates belonging to the # current cluster idxs = np.where(clustering.labels_ == l)[0] # extract the y-coordinates from the elements in the current # cluster, then sort them from top-to-bottom yCoords = [coords[1] for i in idxs] sortedIdxs = idxs[np.argsort(yCoords)] # generate a random color for the cluster color = np.random.randint(0, 255, size=(3,), dtype="int") color = [int(c) for c in color] # loop over the sorted indexes for i in sortedIdxs: # extract the text bounding box coordinates and draw the # bounding box surrounding the current element (x, y, w, h) = coords cv2.rectangle(table, (x, y), (x + w, y + h), color, 2) # extract the OCR'd text for the current column, then construct # a data frame for the data where the first entry in our column # serves as the header cols = [ocrText.strip() for i in sortedIdxs] currentDF = pd.DataFrame({cols[0]: cols[1:]}) # concatenate *original* data frame with the *current* data # frame (we do this to handle columns that may have a varying # number of rows) df = pd.concat([df, currentDF], axis=1) # replace NaN values with an empty string and then show a nicely # formatted version of our multi-column OCR'd text df.fillna("", inplace=True) print(tabulate(df, headers="keys", tablefmt="psql")) # write our table to disk as a CSV file print("[INFO] saving CSV file to disk...") df.to_csv(args["output"], index=False) # show the output image after performing multi-column OCR cv2.imshow("Output", image) cv2.waitKey(0 Continue reading...