Indeed, the essence of these patterns is the same. They both solve the problem of data inconsistency resulting from message send/receive errors.
Inbox guarantees that a message will be received at least once - i.e., there will never be a situation where some work was scheduled but never performed.
Outbox guarantees that a message will be sent at least once - i.e., there will never be a situation where some work was performed but nobody was acknowledged about this.
Both of these patterns use a table in the DB for the same purpose - as an intermediate buffer for messages (inbox for incoming, and outbox for outgoing), from which messages are then read out by a separate worker and processed.
Moreover, these patterns can be used together - the same worker reads a message from the inbox, executes business logic with it, and writes a new message to the outbox.
A good article on this topic: Microservices 101: Transactional Outbox and Inbox