lsgrmSplitter.txx 4.64 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
#ifndef __LSGRM_SPLITTER_TXX
#define __LSGRM_SPLITTER_TXX

namespace lsgrm
{
	template <class TInputImage>
	void SplitOTBImage(const std::string& inputImagePath, // Path to the input image
					   const std::string& ouputDirectoryPath, // Path to the directory storing the tiles
					   unsigned int& tileWidth, // width of the tile
					   unsigned int& tileHeight, // height of the tile
					   const unsigned int margin, // stability margin
					   const unsigned int niter)
	{

		/* Some convenient typedefs to short the code. */
		using ImageType = TInputImage;
		using InternalPixelType = typename ImageType::InternalPixelType;
		using Extractor = otb::MultiChannelExtractROI<InternalPixelType, InternalPixelType>;
		using Reader = otb::ImageFileReader<ImageType>;
		using Writer = otb::ImageFileWriter<ImageType>;

		/* Read the input image and update information about its dimension */
		auto reader = Reader::New();
		reader->SetFileName(inputImagePath);
		reader->UpdateOutputInformation();
		auto imagePtr = reader->GetOutput();
		auto imageWidth = imagePtr->GetLargestPossibleRegion().GetSize()[0];
		auto imageHeight = imagePtr->GetLargestPossibleRegion().GetSize()[1];
		auto imageBands = imagePtr->GetNumberOfComponentsPerPixel();

		if(tileWidth + 2*margin >= imageWidth || tileHeight + 2* margin >= imageHeight)
		{
			std::cout << "One dimension of the tile is greater than the image" << std::endl;
			exit(1);
		}

		// Determine final size of the tiles according to the dimension of the image
		unsigned int k = std::ceil(imageWidth / tileWidth);
		while(imageWidth % k)
			k++;
		tileWidth = imageWidth / k;
		assert(tileWidth > 0);
		k = std::ceil(imageHeight / tileHeight);
		while(imageWidth % k)
			k++;
		tileHeight = imageHeight / k;
		assert(tileHeight > 0);
			
		
		/* Determine the number of tiles according to the tile dimension given by the user. */
		const unsigned int nbTilesX = imageWidth / tileWidth + ( imageWidth % tileWidth > 0 ? 1 : 0);
		const unsigned int nbTilesY = imageHeight / tileHeight + ( imageHeight % tileHeight > 0 ? 1 : 0);

		/* Open text file to record general parameters for the LSGRM library. */
		std::ofstream lsgrmLog(ouputDirectoryPath + "info.txt");
		assert(lsgrmLog.good());
		lsgrmLog << "Image width:"<< imageWidth << "\n" 
				 << "Image height:"<< imageHeight << "\n"
				 << "Number of bands:"<< imageBands << "\n"
				 << "Number of tiles according to X:" << nbTilesX << "\n"
				 << "Number of tiles according to Y:" << nbTilesY << "\n"
				 << "Tile width:" << tileWidth << "\n"
				 << "Tile height:" << tileHeight << "\n"
				 << "Stability Margin value:" << margin << "\n"
				 << "Number of iterations: " << niter << "\n";

		/* Local variables for the next loop */
		unsigned int startX, startY; // Upper left coordinates of the tile.
		unsigned int sizeX, sizeY; // Size of the tiles.
		
		/* Loop over the tiles*/
		for(unsigned int row = 0; row < nbTilesY; ++row)
		{
			for(unsigned int col = 0; col < nbTilesX; ++col)
			{

				startX = col * tileWidth;
				startY = row * tileHeight;
				sizeX = std::min(tileWidth, static_cast<unsigned int>(imageWidth - startX));
				sizeY = std::min(tileHeight, static_cast<unsigned int>(imageHeight - startY));

				lsgrmLog << "Tile " << row*nbTilesY + col << ":"
						 << startX << "," << startY << "," << sizeX << "," << sizeY << ",";

				/* Margin at the top ? */
				if( row > 0 ) 
				{
					startY -= margin;
					sizeY += margin;
					lsgrmLog << "1,";
				}else
					lsgrmLog << "0,";

				/* Margin at the right */
				if( col < nbTilesX - 1 )
				{
					sizeX += margin;
					lsgrmLog << "1,";
				}
				else
					lsgrmLog << "0,";

				/* Margin at the bottom */
				if( row < nbTilesY - 1)
				{
					sizeY += margin;
					lsgrmLog << "1,";
				}
				else
					lsgrmLog << "0,";

				/* Margin at the left */
				if( col > 0 )
				{
					startX -= margin;
					sizeX += margin;
					lsgrmLog << "1\n";
				}
				else
					lsgrmLog << "0\n";

				/* Extract the tile */
				auto extractPtr = Extractor::New();
				extractPtr->SetStartX(startX);
				extractPtr->SetStartY(startY);
				extractPtr->SetSizeX(sizeX);
				extractPtr->SetSizeY(sizeY);

				/* Write the tile to the ouput directory. */
				auto writer = Writer::New();
				writer->SetFileName(ouputDirectoryPath + "tile_" + std::to_string(row) +
									"_" + std::to_string(col) + ".tif");

				/* OTB streaming pipeline */
				extractPtr->SetInput(reader->GetOutput());
				writer->SetInput(extractPtr->GetOutput());
				writer->Update();
				
			} // end for(unsigned int col = 0; col < nbTilesX; ++col)

		} // for(unsigned int row = 0; row < nbTilesY; ++row)

		/* Close the lsgrm info file. */
		lsgrmLog.close();
	}
} // end of namespace lsgrm
#endif