1

I'm comparitively new to using CSV functions in python and need your help.

I have a python program that calculates distance between contours in opencv as well as angle, and this data is later stored in CSV file each time I press h on keyboard. The issue is that, each time I press h, the earlier line gets overwritten by the new line instead of saving it in new line. Is there any way I can save the new variable in new line in CSV format?

Here's part of my code. The whole code is long, so posting necessary part from it-



def calcDistHex(x6, y6, x5, y5, x4, y4, x3, y3, x2, y2, x, y):
    dist1 = round(dist.euclidean((x6, y6), (x5, y5)))
    dist2 = round(dist.euclidean((x5, y5), (x4, y4)))
    dist3 = round(dist.euclidean((x4, y4), (x3, y3)))
    dist4 = round(dist.euclidean((x3, y3), (x2, y2)))
    dist5 = round(dist.euclidean((x2, y2), (x, y)))
    dist6 = round(dist.euclidean((x, y), (x6, y6)))
    
    #print(dist1)
    cv2.putText(frame, str(dist1), (round(0.5 * x6 + 0.5 * x5), round(0.5 * y6 + 0.5 * y5)) , font, 0.5, (0, 0, 0), 1)
    cv2.putText(frame, str(dist2), (round(0.5 * x5 + 0.5 * x4), round(0.5 * y5 + 0.5 * y4)) , font, 0.5, (0, 0, 0), 1)
    cv2.putText(frame, str(dist3), (round(0.5 * x4 + 0.5 * x3), round(0.5 * y4 + 0.5 * y3)) , font, 0.5, (0, 0, 0), 1)
    cv2.putText(frame, str(dist4), (round(0.5 * x3 + 0.5 * x2), round(0.5 * y3 + 0.5 * y2)) , font, 0.5, (0, 0, 0), 1)
    cv2.putText(frame, str(dist5), (round(0.5 * x2 + 0.5 * x), round(0.5 * y2 + 0.5 * y)) , font, 0.5, (0, 0, 0), 1)
    cv2.putText(frame, str(dist6), (round(0.5 * x + 0.5 * x6), round(0.5 * y + 0.5 * y6)) , font, 0.5, (0, 0, 0), 1)

    pt6 = x6, y6
    pt5 = x5, y5
    pt4 = x4, y4
    pt3 = x3, y3
    pt2 = x2, y2
    pt1 = x, y
    
    m2 = gradient(pt2,pt1)
    n2 = gradient(pt2,pt3)
    if m2 is not None and n2 is not None:
        angR2 = math.atan((n2-m2)/(1+(n2*m2)))
        angD2 = math.degrees(angR2)
        if math.isnan(angD2) is False:
            cv2.putText(frame, str(round(abs(angD2))), (pt2[0]-40,pt2[1]-20), font, 1, (0, 0, 0))        
            #print(round(abs(angD2)),(pt1[0]-40,pt1[1]-20))
    
    m3 = gradient(pt3,pt2)
    n3 = gradient(pt3,pt4)
    if m3 is not None and n3 is not None:
        angR3 = math.atan((n3-m3)/(1+(n3*m3)))
        angD3 = math.degrees(angR3)
        if math.isnan(angD3) is False:
            cv2.putText(frame, str(round(abs(angD3))), (pt3[0]-40,pt3[1]-20), font, 1, (0, 0, 0))        
            #print(round(abs(angD3)),(pt1[0]-40,pt1[1]-20))
    
    m4 = gradient(pt4,pt3)
    n4 = gradient(pt4,pt5)
    if m4 is not None and n4 is not None:
        angR4 = math.atan((n4-m4)/(1+(n4*m4)))
        angD4 = math.degrees(angR4)
        if math.isnan(angD4) is False:
            cv2.putText(frame, str(round(abs(angD4))), (pt4[0]-40,pt4[1]-20), font, 1, (0, 0, 0))        
            #print(round(abs(angD4)),(pt1[0]-40,pt1[1]-20))
    
    m5 = gradient(pt5,pt4)
    n5 = gradient(pt5,pt6)
    if m5 is not None and n5 is not None:
        angR5 = math.atan((n5-m5)/(1+(n5*m5)))
        angD5 = math.degrees(angR5)
        if math.isnan(angD5) is False:
            cv2.putText(frame, str(round(abs(angD5))), (pt5[0]-40,pt5[1]-20), font, 1, (0, 0, 0))                
            #print(round(abs(angD5)),(pt1[0]-40,pt1[1]-20))
    
    m6 = gradient(pt6,pt5)
    n6 = gradient(pt6,pt1)
    if m6 is not None and n6 is not None:
        angR6 = math.atan((n6-m6)/(1+(n6*m6)))
        angD6 = math.degrees(angR6)
        if math.isnan(angD6) is False:
            cv2.putText(frame, str(round(abs(angD6))), (pt6[0]-40,pt6[1]-20), font, 1, (0, 0, 0))        
            #print(round(abs(angD6)),(pt1[0]-40,pt1[1]-20))
    
    m = gradient(pt1,pt6)
    n = gradient(pt1,pt2)
    if m is not None and n is not None:
        angR = math.atan((n-m)/(1+(n*m)))
        angD = math.degrees(angR)
        if math.isnan(angD) is False:
            cv2.putText(frame, str(round(abs(angD))), (pt1[0]-40,pt1[1]-20), font, 1, (0, 0, 0))                
            #print(round(abs(angD)),(pt1[0]-40,pt1[1]-20))
    if cv2.waitKey(1) == ord('h'):
            timestamp = int(time.time() * 10000)
            with open('dataset.csv', 'w', newline='') as dataset_file:
                dataset = csv.DictWriter(
                    dataset_file,
                    ["timestamp", "shape", "Side1", "Side2", "Side3", "Side4", "Side5", "Side6", "Perimeter", "Angle1", "Angle2", "Angle3", "Angle4", "Angle5", "Angle6", "AngleSum", "Error"]
                )
                dataset.writeheader()
                dataset.writerow({
                    "timestamp": timestamp,
                    "shape": "Hexagon",
                    "Side1": dist1,
                    "Side2": dist2,
                    "Side3": dist3,
                    "Side4": dist4,
                    "Side5": dist5,
                    "Side6": dist6,
                    "Perimeter": (dist1 + dist2 + dist3 + dist4 + dist5 + dist6),
                    "Angle1": angD,
                    "Angle2": angD2,
                    "Angle3": angD3,
                    "Angle4": angD4,
                    "Angle5": angD5,
                    "Angle6": angD6,
                    "AngleSum": (angD + angD2 + angD3 + angD4 + angD5 + angD6),
                    "Error": "To Do"

                })
                
    return dist1, dist2, dist3, dist4, dist5, dist6, angD, angD2, angD3, angD4, angD5, angD6;

This is the defined function which stores the file.

This function is later called in another loop -

            if len(approx) == 6:
                for j in n:
                    if(i % 2 == 0):
                        x6 = n[i - 10]
                        y6 = n[i - 9]
                        
                        x5 = n[i - 8]
                        y5 = n[i - 7]

                        x4 = n[i - 6]
                        y4 = n[i - 5]

                        x3 = n[i - 4]
                        y3 = n[i - 3]
                        
                        x2 = n[i - 2]
                        y2 = n[i - 1]
                        
                        x = n[i]
                        y = n[i + 1]
                        
                        #print(x, y, x2, y2, x3, y3, x4, y4)
                        string = str(x) + " " + str(y)
                        cv2.circle(frame, (x, y), 2, (0,0,100), 2)                            
                        cv2.putText(frame, string, (x, y), font, 0.5, (138, 138, 54), 2)

                        calcDistHex(x6, y6, x5, y5, x4, y4, x3, y3, x2, y2, x, y)
                                
                                    # text on remaining co-ordinates.

                i = i + 1

    cv2.imshow("Frame", frame)
    cv2.imshow("Mask", threshold)

Any help is appreciated. Written in python.

  • 1
    You write open the file with w, you need to open it with a https://stackoverflow.com/questions/6878628/opening-a-file-for-append – JeffUK May 14 '21 at 12:03

1 Answers1

-1

Try changing this line :

with open('dataset.csv', 'w', newline='') as dataset_file:

By :

with open('dataset.csv', 'a', newline='') as dataset_file:

The 'w' means overwrite. The 'a' means append. More info here : https://stackoverflow.com/a/1466036/3922534

Edit : to avoid the duplicated header at each write, delete the line :

dataset.writeheader()

from your current code, and add the following code before your program's loop. It will itinialize the file by overriding it with the CSV header (notice the 'w' mode), then the loop inside your program will only add the rows of data.

with open('dataset.csv', 'w', newline='') as dataset_file:
    dataset = csv.DictWriter(
        dataset_file,
        ["timestamp", "shape", "Side1", "Side2", "Side3", "Side4", "Side5", "Side6", "Perimeter", "Angle1", "Angle2", "Angle3", "Angle4", "Angle5", "Angle6", "AngleSum", "Error"]
    )
    dataset.writeheader()
Mathieu Rollet
  • 2,016
  • 2
  • 18
  • 31