0

i have yielded 2 functions

        times = []
    total = 0
    is_round = False
    average = str(datetime.timedelta(seconds=0))[2:7]

    while True:
        success, img = video.read()
        image = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        mask = cv2.inRange(image, lower, upper)
        blur = cv2.GaussianBlur(mask, (15, 15), 0)

        circles = cv2.HoughCircles(blur, cv2.HOUGH_GRADIENT, 1, 14,
                                   param1=34, param2=10, minRadius=4, maxRadius=10)

        circles = np.uint16(np.around(circles))

        if (len(circles[0, :]) == 7) and not is_round:
            start_time = time.time()
            is_round = True
            curr_count = 0
            round_total = 0

        elif is_round:
            if len(circles[0, :]) == 1:
                end_time = time.time()
                is_round = False
                time_taken = end_time - start_time
                print('Round time: ', str(
                    datetime.timedelta(seconds=time_taken))[2:7])

                times.append(time_taken)
                average = sum(times) / len(times)
                print('Average time: ', str(
                    datetime.timedelta(seconds=average))[2:7])

            elif len(circles[0, :]) < 7:
                curr_count = (7 - round_total) - len(circles[0, :])
                total += curr_count
                round_total += curr_count

            for i in circles[0, :]:
                cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)
                cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 3)

        yield dict(total=total, average=average)


@app.route("/")
def home():
    return render_template('theme1.html')


gen_total = Tracking()
total, average = next(gen_total)
# initate the function out of the scope of update route


@app.get("/update")
def update():
    return jsonify(next(gen_total))


if __name__ == "__main__":

    app.run(debug=True)

average is a value that uses time.time so it returns a number to the webpage e.g 16.553839.. i need to make it so it returns the time in minutes and seconds e.g 16:55. I have the following code that does this

str(datetime.timedelta(seconds=average))[2:7]

i need to print this to the webpage, when i try yielding this value as a string i get an error

TypeError: unsupported type for timedelta seconds component: str
    <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script>
        function update(){
            $.get("/update", function(data){
                $("#total").html(data.total)
                $("#average").html(data.average.toFixed(2).replace(".", ":"))
            });
        }
        update()
        var intervalId = setInterval(function() {
            update()
        }, 1000);


    </script>

How do i solve this? Thanks.

Ethan0619
  • 25
  • 1
  • 6
  • This code works fine for me. ```str(datetime.timedelta(seconds=1000))[2:7] # => '16:40'```. Please provide a [mcve]. – ggorlen Jul 24 '22 at 04:30
  • the value after seconds needs to be 'average', i'm using opencv so the program is checked every so often meaning the average number can change, it does work when i put seconds=1000 but it needs to be able to change, i still get the error: TypeError: unsupported type for timedelta seconds component: str – Ethan0619 Jul 24 '22 at 05:41
  • Have you tried printing the value of `average` just before the error? What value is it? I tried it with positive, negative numbers, floats and `None` and none of them reproduced the error you're showing. More information is needed to make this actionable. – ggorlen Jul 24 '22 at 05:42
  • Before a while true average = str(datetime.timedelta(seconds=0))[2:7]. after while true: elif is_round: if len(circles[0, :]) == 1: end_time = time.time() time_taken = end_time - start_time times.append(time_taken) average = sum(times) / len(times) print('Average time: ', str( datetime.timedelta(seconds=average))[2:7]) – Ethan0619 Jul 24 '22 at 06:03
  • Thanks, but that's not what I'm asking for. But if you have more code, please [edit] the post so it's comprehensible. What I'm looking for is not the code, but the value of the variable if you `print(average)` just before the crashing line. What does the print show? That'll help reproduce the problem so I can see what's causing the crash. We're still missing a runnable [mcve] here. I should be able to copy, paste and execute the code and see the problem, otherwise it's virtually impossible to help. – ggorlen Jul 24 '22 at 06:09
  • average [swscaler @ 000001b738545080] Warning: data is not aligned! This can lead to a speed loss – Ethan0619 Jul 24 '22 at 11:41
  • 00:00 average [swscaler @ 00000165daf46080] Warning: data is not aligned! This can lead to a speed loss – Ethan0619 Jul 24 '22 at 11:49
  • sorry i [ut it in the wrong place – Ethan0619 Jul 24 '22 at 11:49
  • when i use the line you provided i still get TypeError: unsupported type for timedelta seconds component: str [swscaler @ 000002e3c0b46080] Warning: data is not aligned! This can lead to a speed loss – Ethan0619 Jul 24 '22 at 11:51
  • i have provided more code – Ethan0619 Jul 24 '22 at 11:53
  • There's your error then. Don't pass a `swscaler` where `seconds` expects a number. The `print(average)` isn't supposed to solve the TypeError immediately. The point is to help you solve it by showing what you're passing into `timedelta` that it doesn't like. – ggorlen Jul 24 '22 at 14:27
  • This also seems like an [xy problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/233676#233676) because there's not enough context to show a better way to obtain whatever date format you're trying to achieve. We're stuck battling problem Y (using one specific library) without enough info to help, when really there might be a better solution to fundamental problem X, formatting a date in a certain way. – ggorlen Jul 24 '22 at 14:31
  • As I recall from your last post that ended up in a long discussion thread, `average` was stringifiable, so this is a wild guess, but `str(datetime.timedelta(seconds=str(average)))[2:7]` might work--convert the `swscaler` (a type I've never heard of, probably something related to opencv) to a string first. `print(str(swscaler))` might work or might raise an error that could be useful to see, and even if it does work, the date format might not like whatever `str(swscaler)` returns and might still fail (worth seeing that error too). If it does, take a step back and show input and desired output. – ggorlen Jul 24 '22 at 14:34
  • TypeError: unsupported type for timedelta seconds component: str [swscaler @ 000001f115346080] Warning: data is not aligned! This can lead to a speed loss... I'm pretty sure you can't change/edit swscaler as it is a warning that opencv hasn't detected any object – Ethan0619 Jul 24 '22 at 17:57
  • if i use yield average = average it prints to the webpage.. an example result being 12.351845026016235 and the output i am looking for is 12:35, as i mentioned when i print to the terminal using str(datetime.timedelta(seconds=average))[2:7]) it works but when i try with flask it doesn't – Ethan0619 Jul 24 '22 at 18:01
  • Is that error you keep repeating for the updated code I shared in my last post as well? You could format this on the client with `data.average.toFixed(2).replace(".", ":")`. We're not trying to edit/change swscaler, we're trying to get the underlying number from it so we can format it properly. I'm a broken record, but it's extremely hard to help without a [mcve] and almost always results in endless back and forth like this, which isn't helpful for you. The time it'd take to make a reproducible example will save you (and me) time in the long haul. – ggorlen Jul 24 '22 at 18:42
  • i don't understand... what else do you need? i've sent you the code and i have shared with you the desired output – Ethan0619 Jul 24 '22 at 18:55
  • oh wait hang on – Ethan0619 Jul 24 '22 at 18:57
  • This code is starting to work.. however it is now displaying the seconds in the minutes section e.g 8:33.. how do i sort this? – Ethan0619 Jul 24 '22 at 18:58
  • and when it gets past 60 seconds it stays in seconds and milliseconds – Ethan0619 Jul 24 '22 at 19:09
  • The issue is that the code isn't runnable or complete, and the specification for what you're trying to achieve is unclear. If it was clear, I'd be able to give you a straightforward, direct and unambiguous answer. It seems to be an XY problem because you want to format the date, but formatting it on the frontend might make more sense than formatting it on the backend. It seems like we're moving towards that being the solution, but the expected input/output isn't clear to me. – ggorlen Jul 24 '22 at 20:15
  • If we can isolate it purely to the front end, then what does "average" represent -- what are the valid values, and what is the expected output? I don't think my above `toFixed` makes sense because you need it as the seconds part of a date or some sort of time delta. Please [edit] the post to show the full specification for what average gets converted to. – ggorlen Jul 24 '22 at 20:18
  • yes.. formatting on frontend makes more sense.. as i said my only problem now is that the output is in seconds.. for example 5:02 was an output i got when running for 5 seconds, i fixed this by dividing average by 60 however this does not work if seconds goes past 60, for example i tried it and got an output 0:72 whereas it should be 1:12 – Ethan0619 Jul 24 '22 at 20:21
  • This doesn't answer the question of what output is expected for what inputs or what average represents. Let's say I have the average of 12379. What does this mean and how should this value look and why? What about a few other example values? If you can share this I think I have enough information to figure out your specification. – ggorlen Jul 24 '22 at 20:22
  • OK, that seems clearer--so 12379 is a total number of seconds, which should translate to `50:19` and 240 `04:00`? Do you want [Javascript seconds to minutes and seconds](https://stackoverflow.com/questions/3733227/javascript-seconds-to-minutes-and-seconds)? – ggorlen Jul 24 '22 at 20:27
  • yes.. sorry, i posted that comment before i read your response.. but yes that is the desired result i am looking for – Ethan0619 Jul 24 '22 at 20:28
  • I've added the javascript code to my question.. i'm not sure how to apply it but i'm guessing it would work – Ethan0619 Jul 24 '22 at 20:31
  • Plop in one of the functions [like this one](https://stackoverflow.com/a/26206645/6243352) and call it with your `data.average`: `$("#average").html(secondsToMinSecPadded(data.average))`. – ggorlen Jul 24 '22 at 20:40
  • i don't think this worked... i got output 00:82.. i'm guessing that was 8 seconds – Ethan0619 Jul 24 '22 at 20:44
  • Is average something other than seconds? `average / 10` first? It'd still really help to specify "for `average = 123` I should get `__:__`" for a few values so we know what the input and output are supposed to be. What was the input for `00:82` and you expect `00:08` for ...? – ggorlen Jul 24 '22 at 22:05
  • i've fixed it :) cheers.. if you want to make a separate answer using toFixed i'll accept it – Ethan0619 Jul 24 '22 at 22:09
  • Great! I still don't know what I'm answering so I'll let you post a [self answer](https://stackoverflow.com/help/self-answer). – ggorlen Jul 24 '22 at 22:11

1 Answers1

0

time.time() returns Unix timestamp.

https://docs.python.org/3/library/time.html#time.time

timestamp can be convertted to datetime by datetime.datetime.fromtimestamp.

then, use .strftime() to convert datetime to string.

Example:

>>> timestamp_now = time.time()
>>> datetime.datetime.fromtimestamp(timestamp_now).strftime("%M:%S")
'55:54'
akiraueno
  • 57
  • 4
  • Hi, i added the fromtimestamp line to the yield and got error: TypeError: an integer is required (got type str) – Ethan0619 Jul 24 '22 at 00:03
  • Argument of `fromtimestamp()` is timestamp not string. I guess `datetime.datetime.fromtimestamp(average).strftime("%M:%S")` may be what you want. – akiraueno Jul 24 '22 at 00:15
  • i changed it and received the same error: yield dict(total=total, average=datetime.datetime.fromtimestamp(average).strftime("%M:%S")) TypeError: an integer is required (got type str) – Ethan0619 Jul 24 '22 at 00:20
  • I guess the `average` is not timestamp but string. What about `datetime.datetime.fromtimestamp(float(average)).strftime("%M:%S")`? – akiraueno Jul 24 '22 at 00:31
  • Think were getting closer haha.... ValueError: could not convert string to float: '00:00' – Ethan0619 Jul 24 '22 at 00:34
  • The average variable doesn't have a value to start with... something has to happen before it changes (program uses opencv) – Ethan0619 Jul 24 '22 at 00:35