A few other things that weren't mentioned so far:

In a few places, you do something like this:

    f"{adjust}{os.path.basename(self.p).strip('.jpg') + ' ' + username}"

Why not simply:

    f"{adjust}{os.path.basename(self.p).strip('.jpg')} {username}"

Speaking of which, your use of `str.strip` doesn't behave the way you think it does. Take a look:

    >>> help(str.strip)
    Help on method_descriptor:
    
    strip(self, chars=None, /)
        Return a copy of the string with leading and trailing whitespace remove.
        
        If chars is given and not None, remove characters in chars instead.
    
    >>> 

In your case, the optional `chars` parameter is not `None`, it's `".jpg"`. That means it will remove any of the characters specified in `chars`. Not only that, but since you're using `str.strip` instead of `str.rstrip`, you're potentially removing those characters not just from the back, but from the front as well.

For example:

    >>> "john_help.jpg".strip(".jpg")
    'ohn_hel'
    >>>

Definitely not the desired output in your case.
Using `str.rstrip` would strip only from the back of the string, but it still wouldn't give you the desired result:

    >>> "john_help.jpg".rstrip(".jpg")
    'john_hel'
    >>>

If you're using Python 3.4+, you're better of using `pathlib` anyway instead of all that `os.path` stuff:

    >>> from pathlib import Path
    >>> Path("root/dir/sub/file.jpg").stem
    'file'
    >>> 

I would also suggest using an `enum.Enum` to represent the possible values / options / states of your `tk.Radiobutton`s. It prevents you from "stringify-ing" the options or doing something like this:

    val = item.get()  #radiobutton value
    if val == 2:  # checks if yes
        cells[1].text = "*"
    elif val == 1:   # checks if no
        cells[2].text = "*"
    elif val == 0:   # checks if N/A
        cells[3].text = "*"

Here's how I might set up a `tk.Radiobutton` using an enum:


    import tkinter as tk
    
    
    class Application(tk.Tk):
    
        from enum import Enum
    
    
        class RadioOption(Enum):
            Red = 0
            Green = 1
            Blue = 2
    
        def __init__(self, *args, **kwargs):
            
            tk.Tk.__init__(self, *args, **kwargs)
            self.title("Title")
            self.geometry("100x100")
            self.resizable(width=False, height=False)
    
            self.radio_variable = tk.Variable(None, Application.RadioOption.Red)
    
            def on_radio_variable_change(*args):
                print(self.radio_variable.get())
            self.radio_variable.trace(mode="w", callback=on_radio_variable_change)
    
            self.radio_button_red = tk.Radiobutton(
                self,
                text="Red",
                variable=self.radio_variable,
                value=Application.RadioOption.Red,
            )
    
            self.radio_button_green = tk.Radiobutton(
                self,
                text="Green",
                variable=self.radio_variable,
                value=Application.RadioOption.Green,
            )
    
            self.radio_button_blue = tk.Radiobutton(
                self,
                text="Blue",
                variable=self.radio_variable,
                value=Application.RadioOption.Blue,
            )
    
            self.radio_button_red.pack(anchor=tk.W)
            self.radio_button_green.pack(anchor=tk.W)
            self.radio_button_blue.pack(anchor=tk.W)
    
    def main():
    
        application = Application()
        application.mainloop()
        
        return 0
    
    
    if __name__ == "__main__":
        import sys
        sys.exit(main())


And one more tiny nit-pick, in a few different places you do something like this:

    self.open_button.grid(row=502, column=0)
    self.resetBtn = Button(main, text = "reset", command = reset)

See how some of the keyword-arguments have additional whitespace, and others do not? Pick one style, but don't do both - personally I would remove the whitespace since that's PEP8 compliant.