ソースを参照

Add commentaires, copyright

zhJ 6 ヶ月 前
コミット
d6feafb82d
1 ファイル変更69 行追加19 行削除
  1. 69 19
      LigneForce.py

+ 69 - 19
LigneForce.py

@@ -1,3 +1,18 @@
+#Copyright (C) [2023] [ZHANG Jing, Université du Littoral Côte d'Opale]
+#
+#This program is free software: you can redistribute it and/or modify
+#it under the terms of the GNU General Public License as published by
+#the Free Software Foundation, either version 3 of the License, or
+#(at your option) any later version.
+#
+#This program is distributed in the hope that it will be useful,
+#but WITHOUT ANY WARRANTY; without even the implied warranty of
+#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#GNU General Public License for more details.
+#
+#You should have received a copy of the GNU General Public License
+#along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 #!/usr/bin/env python
 # coding: utf-8
 
@@ -15,7 +30,14 @@ from skimage.transform import resize
 
 from PIL import Image, ImageDraw, ImageColor
 
-
+## compute image gradient map, take the absolute difference values in 4 dimensions for each pixel
+  
+#        --------------------------
+#       |                          |
+#       |          i,  j   i,  j+1 |
+#       | i+1,j-1  i+1,j   i+1,j+1 |
+#        --------------------------
+  
 def gradient4D(img):
     (row, col) = img.shape
     g4d = np.zeros((row, col))
@@ -26,18 +48,22 @@ def gradient4D(img):
             
     return npNormalise(g4d)
 
-
+# normalise values to [0, 1]
 def npNormalise(xArray):
     XNorm = (xArray - xArray.min()) / (xArray.max() - xArray.min())
     return XNorm
 
+# compute all potential lines for a square of size ws*ws
+# input : length of the square
+# output : 1. a set of binary images, each image contains only one line
+#           2. a set containing the coordinates of the start points and the end points of the line
 def getBaseLines(ws):
     baseLineList = []
     baseLineListIdex = []
+    # Skip 5 pixels to avoid lines near edges
     for i in range(0,ws-5):
-        #if i == 1: break
         for j in range(5,ws):  #  cut bord
-            #if j == 6: break
+            
     #               1
     #         -------------
     #         |           |
@@ -46,33 +72,39 @@ def getBaseLines(ws):
     #         |           |
     #         --------------
     #               3
-            # adjacent edge
+            # adjacent edge   (like edge 1 and edge 2, edge 1 and edge 4)
             img12 = Image.new('F', (ws,ws),0)
             draw12 = ImageDraw.Draw(img12)
+            # lines that the start point in edge 1 and the end point in edge 2
             draw12.line(xy=(i, 0, ws-1, j),
                       fill=(1), width = 1)
             baseLineList.append(np.asarray(img12)) 
             baseLineListIdex.append(np.asarray([[i, 0],[ws-1, j]]))
+            # lines that the start point in edge 4 and the end point in edge 1
             baseLineList.append(np.rot90(np.asarray(img12), 1, axes=(0, 1)))
             baseLineListIdex.append(np.asarray([[j, 0],[0, ws-1-i]]))
+            # lines that the start point in edge 3 and the end point in edge 4
             baseLineList.append(np.rot90(np.asarray(img12), 2, axes=(0, 1)))
             baseLineListIdex.append(np.asarray([[0, ws-1-j],[ws-1-i, ws-1]]))
+            # lines that the start point in edge 2 and the end point in edge 3
             baseLineList.append(np.rot90(np.asarray(img12), 3, axes=(0, 1)))
             baseLineListIdex.append(np.asarray([[ws-1, i],[ws-1-j, ws-1]]))
 
             # opposite side
             img13 = Image.new('F', (ws,ws),0)
             draw13 = ImageDraw.Draw(img13)
+            # lines that the start point in edge 4 and the end point in edge 2
             draw13.line(xy=(i, 0, j, ws-1),
                       fill=(1), width = 1)
             baseLineList.append(np.asarray(img13)) 
             baseLineListIdex.append(np.asarray([[i,0],[j, ws-1]]))
+            # lines that the start point in edge 1 and the end point in edge 3
             baseLineList.append(np.asarray(img13).T) 
             baseLineListIdex.append(np.asarray([[0,i],[ws-1, j]]))
     print('base line number :', len(baseLineList))
     return np.asarray(baseLineList), np.asarray(baseLineListIdex)
 
-
+# Calculate the slope of the line formed by vertex1 and vertex2
 def calculSlope(v1,v2):
     difX = v2[0] - v1[0]
     difY = v2[1] - v1[1]
@@ -82,14 +114,17 @@ def calculSlope(v1,v2):
         lk = difY / difX
     return lk
 
+# Compute the band mask of a line
 def clusterRegion(centerLine, scale = 4, windowSize=64):
     H = windowSize
     W = windowSize
     sMask = np.zeros([H,W])
     ix = int(centerLine[0][0])
     iy = int(centerLine[0][1])
+    # calculate the width of band mask
     pixelRange = int(min(H,W) / scale)  #  scale = 10 
     
+    # get the slope of line
     k = calculSlope(centerLine[0],centerLine[1])
 
     if abs(k) > 1:  
@@ -125,32 +160,41 @@ def clusterRegion(centerLine, scale = 4, windowSize=64):
     return sMask
 
 
-
+# fonction for display all the lines
 def drawGroupLine(file, lineList, flineListCluster, scale, functionName, colorSTR, outputPath):
     c = ImageColor.colormap
     cList = list(c.items())
     (inputPath,inputFile) = os.path.split(file)
     print(inputPath)
     print(inputFile)
+    
+    # read the orignal file for draw
     with Image.open(file) as img4draw:
         w, h = img4draw.size
+        if w >h:     # add lineWidth to adapt the visibility of drawing results to different image sizes
+            lineWidth = int(h/40)
+        else:
+            lineWidth = int(w/40)
+            
         scale = 1/64
         wScale = np.ceil(w*scale)
         hScale = np.ceil(h*scale)
         
         img1 = ImageDraw.Draw(img4draw) 
-            
+        
+        # draw the cluster result
 #         for n,lineSet in enumerate(flineListCluster):
 #             for [v1,v2],w,_ in lineSet[1:]:
 #                 img1.line([(v1[0]*wScale,v1[1]*hScale), (v2[0]*wScale,v2[1]*hScale)], fill = cList[int(n*2)+2][1], width = 4)
-        
+        # draw all the centers
         for [v1,v2] in lineList:
-            img1.line([(v1[0],v1[1]), (v2[0],v2[1])], fill = colorSTR, width = 8)
+            img1.line([(v1[0],v1[1]), (v2[0],v2[1])], fill = colorSTR, width = lineWidth)
             
         img4draw.save(os.path.join(outputPath, inputFile[:-4] + '_' + str(functionName) + inputFile[-4:] ))
 
-
+# sort the slope of lines, inutile for version 0
 def sortSlope(lineListArray):
+    print('lineListArray', lineListArray)
     slopeList = []
     groupWeight = 0
     for l in lineListArray:
@@ -161,23 +205,26 @@ def sortSlope(lineListArray):
         slopeList.append(k)
         groupWeight = groupWeight + l[1]
 #         print('weight = ', l[1])
+    print('slopeList : ', slopeList)
     index = np.argsort(np.array(slopeList))
+    print('sortSlope index : ', index)
+    print('sortSlope index median : ', int(np.median(index)))
     #groupWeight = np.mean(groupWeight)
     
-    
     return [lineListArray[int(np.median(index))][0], lineListArray[0][1], lineListArray[int(np.median(index))][2]]
+    # return [lineListArray[int(len(index)/2)][0], lineListArray[0][1], lineListArray[int(len(index)/2)][2]]
 #     index[len(index)//2]
 
+# extraction the center of each group
 def forceLinesClusterIntegration(cluster):
     forceL = []
     
     for i,lineSet in enumerate(cluster):
-
-        forceL.append(sortSlope(lineSet[1:]))
+        forceL.append(lineSet[1])
     return forceL
 
 
-
+# refine the cluster result
 def refine(lineList, fg, wg, iP, ws):
     wlist = []
     forceList = []
@@ -198,18 +245,21 @@ def refine(lineList, fg, wg, iP, ws):
     flList = forceLinesClusterIntegration(forceList)
     return flList     
                 
-
+# the main process of clustering the lines
 def findSaliantLineCluster(gradient4d,allLines,allLinesIndex,ws, orgW, orgH ):
     weightList = []
-    fineGrained0 = 8
-    intePrec0 = 0.8
+    fineGrained0 = 8   # initial refine grained = ws / 8
+    intePrec0 = 0.8    # initial intersection precision
     forceLinesCluster = []
+    
+    # compute weights of lines
     for l in allLines:
         w = np.sum(gradient4d*l)
         weightList.append(w)
 
     npWeightList = np.array(weightList)
-    sortWeightList = npWeightList.argsort()[::-1]   # [::-1] inverse a list
+    sortWeightList = npWeightList.argsort()[::-1]   # [::-1] inverse a list, range from large to small
+    # top 300 weighted candidates, about 0.14% of the total lines
     for n,wId in enumerate(sortWeightList[:300]):
         if n == 0:
             groupMask = clusterRegion(allLinesIndex[wId], fineGrained0, ws)