Inversion of Control is a general concept where normal control flow is “inverted” in some way.
By “normal” flow, I mean a traditional batch application flow: the code runs from beginning to end, creating resources, requesting data and providing output. Control flow is dictated by the application itself, calling into libraries and system facilities as necessary. Any inversion of this — where libraries rather than the application (using these terms somewhat loosely) drive control flow — is in some sense inversion of control.
One of the most common examples of IoC is an event loop. In an event loop, the GUI toolkit (or the operating system) is in control, calling back into your application to handle events and process input. The normal flow — requesting input & processing it — is inverted so that the input processor drives the application, rather than the other way around.
Dependency injection is a specific use of Inversion of Control, where control inversion is applied to the selection and allocation of dependencies. Rather than having a component instantiate the subcomponents it requires, the creating code (either application code, manually, or the DI container) instantiates the required subcomponents and injects them into the component.