1

Using opencv and c++ I am attempting to write a program that given a file path, the program will duplicate every image in that file. This is what I have written using imread and imwrite:

#include <filesystem> #include <fstream> using namespace std; using namespace cv; namespace fs = std::filesystem; Mat duplicateImage(string filename) { // Load the input image Mat image = imread(filename, IMREAD_UNCHANGED); // Create a duplicate image Mat duplicate = image.clone(); return duplicate; } int main(int argc, char** argv) { string directory_name = "C:\\My\\File\\Path\\Name"; vector<string> files_list; ifstream file_stream(directory_name); string line; while (getline(file_stream, line)) { files_list.push_back(line); } // Duplicate each image in the directory for (string filename : files_list) { Mat duplicate = duplicateImage(filename); string output_filename = filename + "_copy"; // new filename for the duplicate; cv::imwrite(output_filename, duplicate); } } 

When I open up the file path there are no changes made to the file.

I had initially attempted to fo this with fstream which resulted in the same issue, the file not being modified at all. any advice would be greatly appriciated!

EDIT: I have discovered a bug - I am not even entering the for loop, I know this because I did a print statement and am not seeing it in the concile. I'm am unsure why I would not be entering the for loop.

6
  • 2
    How will it know whether you want a JPEG or a PNG written if the output filename is inputImage.jpg_copy ? Commented Apr 5, 2023 at 6:42
  • This is not a good way to copy images. You will lose all your metadata (copyright, EXIF, GPS data, camera make/model, ICC colour profiles, IPTC data). You will also potentially change compression factor (making images needlessly larger or smaller and losing quality) and inflate palette images into full RGB images costing disk space. Commented Apr 5, 2023 at 9:11
  • @MarkSetchell The reason im wanting to copy the images is because I need to alter the original image to be a certain size and the copy image to be a different size. do you have any ideas for a different route i could take? Commented Apr 5, 2023 at 16:46
  • It's hard to answer you. I don't know 1) what format your images are 2) how big you want the output images 3) whether you need to retain metadata 4) whether you just want the job done, or are insistant on using OpenCV and C++. Commented Apr 5, 2023 at 16:53
  • @MarkSetchell my images are .jpg currents and My end goal will be to make the duplicate images be 200 * 200, I do not need to retiain the metadata, and I have to use c++ Commented Apr 5, 2023 at 17:14

1 Answer 1

0

There are 2 issues in your code:

1. Getting the list of files:

You cannot use ifstream with getline to get a list of files in a directory (which is why files_list is empty).
You can use std::filesystem::directory_iterator for that.
In your case it should be something like:

for (const auto& entry : std::filesystem::directory_iterator(directory_name)) { files_list.push_back(entry.path().string()); } 

2. Saving the images with cv::imwrite:

As you can see in the cv::imwrite documentation:

The image format is chosen based on the filename extension (see cv::imread for the list of extensions).

(emphasis is mine)

The list of extensions is detailed here: cv::imread. Among them: .jpg (for JPEG files), .png (for Portable Network Graphics), etc.

Since you add a "_copy" suffix to your filenames there are no longer with one of the supported extensions and the image is not saved.

You can use e.g. "_copy.jpg" or "_copy.png" as a suffix.
You can also determine the extension of the current filename dynamically (see here:How to get file extension from string in C++) and add it to the generated filename.

However:

If you only need to copy the image files as is (without modifying the image content), you can simply use std::filesystem::copy without reading the image content etc.

Sign up to request clarification or add additional context in comments.

2 Comments

Hello! thank you for your answer - I changed this line to look like ''' for (string filename : files_list) { Mat duplicate = duplicateImage(filename); string output_filename = filename + "_copy.jpg"; // new filename for the duplicate; cv::imwrite(output_filename, duplicate); } ''' because the images in the file are of the .jpg extension and I am still not seeing any changes in the file. Do you know a reason why that might be?
I think you are not getting the list of files in the directory properly. Updated my answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.