I asked a question about contours, and how to fill blank spaces with "dashed" contour. @LBerger and @sturkmen gently gave me solutions, and I choose the @sturkmen code ( http://pastebin.com/EXuKpgY6 ) because it is easier to implement. However, both are in c++. The original image is :
The desired output (which is also the @sturkmen code's ouput) is :
Taking in account stakeoverflow answers, @sturkmen 's help and @berak 's code/answer http://answers.opencv.org/question/71105/c-to-python-need-help-to-help/ I was able to do some translation.
In order to simplify my problem I used the @berak 's image:
My current code stands as :
import cv2
import numpy as np
def distanceBtwPoints(p0, p1):
return np.sqrt((p0[0] - p1[0])**2 + (p0[1] - p1[1])**2)
def findNearestPointIndex(pt, Points):
mindistance = 1e9
for ip in Points:
print "ip", ip
print "pt", pt
distance = distanceBtwPoints(pt, ip)
print 'distance', distance
if distance < mindistance :
mindistance = distance
nearestpoint = ip
print "nearestpoint", nearestpoint
nearestpointindex = nearestpoint.argmin()
print "nearestpointindex", nearestpoint.argmin()
return nearestpointindex
if __name__ == '__main__':
img = cv2.imread("bridgeTestSource.png")
src = cv2.imread("bridgeTestSource.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.asarray(gray < 127, dtype=np.uint8) # need to cast back to uint8
contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours,-1, (0,0,255), 2)
for i in range(len(contours)):
print "Contour ", i , "points", contours[i]
print
print " - Contour ", i, "area :", cv2.contourArea(contours[i])
print
for j in range(contours[i].shape[0]):
print "contour x y", contours[i][j].squeeze()
print "the contour" , i, "distance between ", contours[i][0].squeeze(),contours[i][1].squeeze(), "is " , distanceBtwPoints(contours[i][0].squeeze(), contours[i][1].squeeze())
cnt = contours[0]
for c in contours:
if cv2.contourArea(cnt) < cv2.contourArea(c):
cnt = c
for c in contours:
if not np.array_equal(cnt, c) and c.shape[0] > 0:
for j in range(c.shape[2]):
pt0 = c[j][0]
cnt_nearIdx = cnt[findNearestPointIndex(pt0, cnt.squeeze())].squeeze()
lcnt_nearIdx = cnt_nearIdx.tolist()
lpt0 = pt0.tolist()
tcnt_nearIdx = tuple(lcnt_nearIdx)
tpt0 = tuple(lpt0)
cv2.line(img,tpt0, tcnt_nearIdx,(0,0,0),1,8)
cv2.imwrite('nimg.jpg', img)
gray_src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
gray_src = np.asarray(gray_src < 127, dtype=np.uint8) # need to cast back to uint8
contours1, hierarchy = cv2.findContours(gray_src, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(src, contours1,-1, (0,0,0), 0)
m_xor= np.ones(src.shape[:2], dtype="uint8") * 255
ncnt = cnt.astype(np.int32)
cv2.polylines(m_xor, [ncnt], 1, (0,0,0))
m_xor = 255 - (src or m_xor)
cv2.imwrite('result.jpg', m_xor)
And I'm facing problems. The image after the lines loop is a mess:
I'm getting errors in m_xor:
m_xor = 255 - (src or m_xor)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
For debug purposes you can see my distance, points, nearest here: http://pastebin.com/NstQXxBk