You are correct that SkImages that are backed by pixels (or an encoded image) are cached as textures on the GPU. The budget for this is controlled by GrDirectContext::setResourceCacheLimit(). And you're also correct that you now have two copies. If the texture copy gets purged and you redraw the image then it gets recreated.
Alternatively, you can call SkImage::makeTextureImage(). This will return a new SkImage that is backed by a texture that is explicitly owned by the SkImage. The texture's lifetime is tied to the SkImage, i.e. it won't get purged under memory pressure. You can control whether the texture's memory counts against the context's memory budget with the SkBudgeted parameter.