Reputation: 35998
I am trying to remove horizontal and vertical lines from my images that look like this:
While googling I found a solution that I believe might work: Extract horizontal and vertical lines by using morphological operations, however, it is in C++.
I have tried converting the solution to Python, but I don't get the same results. In order to keep the image same, I've tried my python version on the same image used in that solution:
Below is my python version with relevant c++ version in the comments:
img = cv2.imread(path)
img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol
#Mat bw;
#adaptiveThreshold(~gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2)
cv2.imwrite("th2.jpg", th2)
#Mat horizontal = bw.clone();
#Mat vertical = bw.clone();
horizontal = th2
vertical = th2
#int horizontalsize = horizontal.cols / 30;
rows,cols = horizontal.shape
horizontalsize = cols / 30
#// Create structure element for extracting horizontal lines through morphology operations
#Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1));
horizontalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (horizontalsize,1))
#// Apply morphology operations
#erode(horizontal, horizontal, horizontalStructure, Point(-1, -1));
#dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1));
#// Show extracted horizontal lines
#imshow("horizontal", horizontal);
horizontal = cv2.erode(horizontal, horizontalStructure, (-1, -1))
horizontal = cv2.dilate(horizontal, horizontalStructure, (-1, -1))
cv2.imwrite("horizontal.jpg", horizontal)
#// Specify size on vertical axis
#int verticalsize = vertical.rows / 30;
verticalsize = rows / 30
#// Create structure element for extracting vertical lines through morphology operations
#Mat verticalStructure = getStructuringElement(MORPH_RECT, Size( 1,verticalsize));
verticalStructure = cv2.getStructuringElement(cv2.MORPH_RECT, (1, verticalsize))
#// Apply morphology operations
#erode(vertical, vertical, verticalStructure, Point(-1, -1));
#dilate(vertical, vertical, verticalStructure, Point(-1, -1));
#// Show extracted vertical lines
#imshow("vertical", vertical);
vertical = cv2.erode(vertical, verticalStructure, (-1, -1))
vertical = cv2.dilate(vertical, verticalStructure, (-1, -1))
cv2.imwrite("vertical.jpg", vertical)
#// Inverse vertical image
#bitwise_not(vertical, vertical);
#imshow("vertical_bit", vertical);
vertical = cv2.bitwise_not(vertical)
cv2.imwrite("vertical_bit.jpg", vertical)
#// Extract edges and smooth image according to the logic
#// 1. extract edges
#// 2. dilate(edges)
#// 3. src.copyTo(smooth)
#// 4. blur smooth img
#// 5. smooth.copyTo(src, edges)
#step1
#Mat edges;
#adaptiveThreshold(vertical, edges, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2);
#imshow("edges", edges);
edges = cv2.adaptiveThreshold(vertical,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,3,-2)
cv2.imwrite("edges.jpg", edges)
#step2
#Mat kernel = Mat::ones(2, 2, CV_8UC1);
#dilate(edges, edges, kernel);
#imshow("dilate", edges);
kernel = np.ones((2, 2), dtype = "uint8")
dilated = cv2.dilate(edges, kernel)
cv2.imwrite("dialted.jpg", dilated)
# step3
#Mat smooth;
#vertical.copyTo(smooth);
smooth = vertical.copy()
#step 4
#blur(smooth, smooth, Size(2, 2));
smooth = cv2.blur(smooth, (2,2))
#step 5
#smooth.copyTo(vertical, edges);
(rows, cols) = np.where(edges != 0)
vertical[rows, cols] = smooth[rows, cols]
// Show final result
#imshow("smooth", vertical);
cv2.imwrite("smooth.jpg", vertical)
I get back
which is not the result that the solution linked above gets.
I belive the problem might be in my conversion of this c++ line:
// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol
Mat bw;
adaptiveThreshold(~gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
to this python line
th2 = cv2.adaptiveThreshold(img,255, cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,15,-2)
Question
How can I best convert the C++ code in the linked solution to Python?
Upvotes: 1
Views: 1251
Reputation: 937
Looks like that you have the problem because of tilde operator that applies bitwise NOT operation to all pixels in the image. Look at this three lines of C++ code:
cv::Mat img = imread("smiley.png", IMREAD_GRAYSCALE);
imshow("Image0", img);
imshow("Image1", ~img); // tilde
These are the images you get:
Quick solution: if you want to apply thresholding correctly then either
Upvotes: 1