程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 分享用於學習C++圖像處理的代碼示例,圖像處理示例

分享用於學習C++圖像處理的代碼示例,圖像處理示例

編輯:C++入門知識

分享用於學習C++圖像處理的代碼示例,圖像處理示例


為了便於學習圖像處理並研究圖像算法,

俺寫了一個適合初學者學習的小小框架。

 

麻雀雖小五髒俱全。

 

采用的加解碼庫:stb_image

官方:http://nothings.org/

 

stb_image.h用於解析圖片格式:

JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC

stb_image_write.h用於保存圖片格式:

PNG, TGA, BMP, HDR

 

附帶處理耗時計算,示例演示了一個簡單的反色處理算法,並簡單注釋了一下部分邏輯。

 

完整代碼:

#include <iostream>
#include <algorithm>

#include <cstdint>
#include <numeric>
#include <math.h>
#include <io.h>

//使用stbImage http://nothings.org/
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h" 

//如果是Windows的話,調用系統API ShellExecuteA打開圖片
#if defined(_MSC_VER)
#include <windows.h> 
#define USE_SHELL_OPEN
#endif

//是否使用OMP方式計時
#define USE_OMP 0

#if  USE_OMP
#include <omp.h>
auto const epoch = omp_get_wtime();
double now() {
	return omp_get_wtime() - epoch; 
};
#else
#include <chrono>
auto const epoch = std::chrono::steady_clock::now();
double now() {
	return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - epoch).count() / 1000.0;
};
#endif

//計時函數
template<typename FN>
double bench(const FN &fn) {
	auto took = -now();
	return (fn(), took + now());
}

//存儲當前傳入文件位置的變量
std::string m_curFilePath;

//加載圖片
void loadImage(const char* filename, unsigned char*& Output, int  &Width, int  &Height, int &Channels)
{
	Output = stbi_load(filename, &Width, &Height, &Channels, 0);
}
//保存圖片
void saveImage(const char* filename, int  Width, int  Height, int Channels, unsigned char* Output, bool open = true)
{
	std::string saveFile = m_curFilePath;
	saveFile += filename;
	//保存為png,也可以調用stbi_write_bmp 保存為bmp
	stbi_write_png(saveFile.c_str(), Width, Height, Channels, Output, 0);

#ifdef USE_SHELL_OPEN
	if (open)
		ShellExecuteA(NULL, "open", saveFile.c_str(), NULL, NULL, SW_SHOW);
#else
	//其他平台暫不實現
#endif
}

//取當前傳入的文件位置
void getCurrentFilePath(const char* filePath, std::string& curFilePath)
{
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char fname[_MAX_FNAME];
	char ext[_MAX_EXT];
	curFilePath.clear();
	_splitpath_s(filePath, drive, dir, fname, ext);
	curFilePath += drive;
	curFilePath += dir;
	curFilePath += fname;
	curFilePath += "_";
}

//算法處理,這裡以一個反色作為例子
void processImage(unsigned char* Input, unsigned char* Output, unsigned int  Width, unsigned int  Height, unsigned int Channels)
{
	int WidthStep = Width*Channels;
	if (Channels == 1)
	{
		for (unsigned int Y = 0; Y < Height; Y++)
		{
			unsigned char*     pOutput = Output + (Y * WidthStep);
			unsigned char*     pInput = Input + (Y * WidthStep);
			for (unsigned int X = 0; X < Width; X++)
			{
				pOutput[0] = 255 - pInput[0];

				//下一個像素點
				pInput += Channels;
				pOutput += Channels;
			}
		}
	}
	else 	if (Channels == 3 || Channels == 4)
	{
		for (unsigned int Y = 0; Y < Height; Y++)
		{
			unsigned char*     pOutput = Output + (Y * WidthStep);
			unsigned char*     pInput = Input + (Y * WidthStep);
			for (unsigned int X = 0; X < Width; X++)
			{
				pOutput[0] = 255 - pInput[0];
				pOutput[1] = 255 - pInput[1];
				pOutput[2] = 255 - pInput[2];
				//通道數為4時,不處理A通道反色(pOutput[3] = 255 - pInput[3];)
				//下一個像素點
				pInput += Channels;
				pOutput += Channels;
			}
		}
	}

}

//本人博客:http://tntmonks.cnblogs.com/轉載請注明出處.

int main(int argc, char **argv) {

	std::cout << "Image Processing " << std::endl;
	std::cout << "Demo By Gaozhihan (Build 2016-03-22)" << std::endl;
	std::cout << "支持解析如下圖片格式:" << std::endl;
	std::cout << "JPG, PNG, TGA, BMP, PSD, GIF, HDR, PIC" << std::endl;

	//檢查參數是否正確
	if (argc < 2)
	{
		std::cout << "參數錯誤。" << std::endl;
		std::cout << "請拖放文件到可執行文件上,或使用命令行:imageProc.exe 圖片" << std::endl;
		std::cout << "例如: imageProc.exe d:\\image.jpg" << std::endl;

		return 0;
	}

	std::string szfile = argv[1];
	//檢查輸入的文件是否存在
	if (_access(szfile.c_str(), 0) == -1)
	{
		std::cout << "輸入的文件不存在,參數錯誤!" << std::endl;
	}

	getCurrentFilePath(szfile.c_str(), m_curFilePath);

	int Width = 0;        //圖片寬度
	int Height = 0;        //圖片高度
	int Channels = 0;    //圖片通道數
	unsigned char* inputImage = NULL;    //輸入圖片指針

	double nLoadTime = bench([&]{
		//加載圖片
		loadImage(szfile.c_str(), inputImage, Width, Height, Channels);
	});
	std::cout << " 加載耗時: " << int(nLoadTime * 1000) << " 毫秒" << std::endl;
	if ((Channels != 0) && (Width != 0) && (Height != 0))
	{
		//分配與載入同等內存用於處理後輸出結果
		unsigned char* outputImg = (unsigned char*)STBI_MALLOC(Width*Channels*Height*sizeof(unsigned char));
		if (inputImage) {
			//如果圖片加載成功,則將內容復制給輸出內存,方便處理
			memcpy(outputImg, inputImage, Width*Channels*Height);
		}
		else     {
			std::cout << " 加載文件: \n" << szfile.c_str() << " 失敗!" << std::endl;
		}

		double nProcessTime = bench([&]{
			//處理算法
			processImage(inputImage, outputImg, Width, Height, Channels);
		});
		std::cout << " 處理耗時: " << int(nProcessTime * 1000) << " 毫秒" << std::endl;

		//保存處理後的圖片
		double nSaveTime = bench([&]{
			saveImage("_done.png", Width, Height, Channels, outputImg);
		});
		std::cout << " 保存耗時: " << int(nSaveTime * 1000) << " 毫秒" << std::endl;

		//釋放占用的內存
		if (outputImg)
		{
			STBI_FREE(outputImg);
			outputImg = NULL;
		}

		if (inputImage)
		{
			STBI_FREE(inputImage);
			inputImage = NULL;
		}
	}
	else
	{
		std::cout << " 加載文件: \n" << szfile.c_str() << " 失敗!" << std::endl;
	}

	getchar();
	std::cout << "按任意鍵退出程序 \n" << std::endl;
	return 0;
}

  

示例具體流程為:

加載圖片->算法處理->保存圖片->打開保存圖片(僅Windows)

並對 加載,處理,保存 這三個環節都進行了耗時計算並輸出。

 

示例代碼下載:

http://files.cnblogs.com/files/tntmonks/imageProcDemo.zip

 

若有其他相關問題或者需求也可以郵件聯系俺探討。

郵箱地址是: 
[email protected]

 

若此博文能幫到您,歡迎掃碼小額贊助。

微信:  

 

 

支付寶: 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved