I'll add an explanation that I've been told is a helpful one.
As you correctly point out, dependency injection is the act of a class demanding its collaborators via constructor or setter injection. You could think of this as a coding technique. Inversion of control, on the other hand, is more of a design technique -- a philosophy, if you will.
In procedural programming (and procedural-style programming in OO languages), you generally have some kind of "command and control" philosophy. If you're creating a house object that consists of three floor objects, which consist of some number of room objects each, you create a house object whose constructor instantiates three floor objects, each of whose constructor, in turn, instantiates room objects.
When you invert control, you're inverting command and control paradigm. With IoC, when I go to instantiate a house, it doesn't take care of all of its details for me. Instead, it says, via its constructor (and dependency injection), "you can't instantiate me without some floors". So, you go to instantiate the floors and they say "nope, not without some rooms". Now, in this "inverted" style, our house doesn't control the creation of the rooms - it leaves that up to someone else and it expresses instead, only what it will do with the rooms it's given. This is desirable because, by flipping command and control on its head, you have better seams for reasoning about and testing the code -- it's easier to deconstruct things into components.
So, to summarize, inversion of control is the philosophy and dependency injection is the means by which it's achieved.