How to detect small holes in the wall
Phát hiện lổ hổng trên tường
The Mathematica Stack Exchange is really a gold mine for image processing learners like us. A few days ago there was someone posted a question about how to detect small holes in walls. I first thought it was a very difficult problem, but it turns out the solution in Mathematica consists only a few lines of code. And I’m really amazed with the brilliance of the Mathematica fellows there.
Trang Mathematica Stack Exchange thật sự là mỏ vàng để học xử lý ảnh. Ít ngày trước có người gửi câu hỏi “làm sao để phát hiện lổ nứt trên tường”. Đầu tiên tôi nghĩ đó là vấn đề rất khó, nhưng sau khi xem giải pháp ở Mathematica chỉ có vài dòng code. Tôi đã thực sự kinh ngạc với các nghiên cứu sinh Mathematica.
Take a look at the image below. There is a little damage on the wall that needs to be located.
Nhìn xem ảnh bên dưới, có vài hư hỏng trên tường cần được xác định.
Figure 1. Image of a wall with small damage. Ảnh bức tường có hư hỏng nhỏ
For more samples, see the original images from MSE: image1, image2, image3,image4. I will be using those images for testing my code below.
Để có nhiều mẫu hơn thì xem các ảnh trên. Tôi sẽ dùng các ảnh này để thử code
A simple and short Mathematica code is given to solve this problem:
Code ở Mathematica đơn giản và ngắn:
1 2 3 4 5 6 7 |
i = {"http://i.stack.imgur.com/KjTp9.png", "http://i.stack.imgur.com/AuHP7.png", "http://i.stack.imgur.com/jFkNM.png"}; i1 = Import /@ i; i2 = ColorNegate /@ Binarize /@ i1; m = Dilation[#, 10]&/@ (Binarize[#, .8]&/@ ImageAdjust/@ DistanceTransform /@ i2); Grid@{i1, ColorCombine[ {#1, #1, #2}] & @@@ Transpose[{i1, m}]} |
Basically the code threshold the images, perform distance transform and find the peaks, then enlarge the contours with dilation. All of the required algorithm is available in OpenCV so I tried to port the code to Python.
Căn bản là code này phân ngưỡng ảnh, thực hiện phép DistanceTransform và tìm đỉnh, rồi mở rộng biên với phép giãn nở. Tất cả thuật toán cần dùng OpenCV đều có nên tôi đã thử chuyển qua Python.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import numpy as np import cv2 def detect_black_areas(filename): m1 = cv2.imread(filename) m2 = cv2.cvtColor(m1, cv2.cv.CV_BGR2GRAY) m3 = 255 - cv2.threshold(m2, 0, 255, cv2.THRESH_OTSU)[1] m4 = cv2.distanceTransform(m3, cv2.cv.CV_DIST_L2, 3) m5 = cv2.normalize(m4, alpha=0., beta=1., norm_type=cv2.NORM_MINMAX) m6 = cv2.threshold(m5, .8, 1., cv2.THRESH_BINARY)[1] m7 = cv2.dilate(m6, np.ones((3,3), np.uint8), iterations=7) cnt = cv2.findContours(m7.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[0] cv2.drawContours(m1, cnt, -1, (0,0,255), 2) cv2.imshow("image", m1) cv2.waitKey() if __name__ == "__main__": files = ["KjTp9.png", "AuHP7.png", "jFkNM.png", "Yksk9.png"] for file in files: detect_black_areas(file) |
The result is pretty amazing as shown below.
Kết quả đẹp 1 cách đáng kinh ngạc.
Figure 2. The result of the program. Kết quả của chương trình
Nguồn http://opencv-code.com/tutorials/how-to-detect-small-holes-in-the-wall/