OpenCVのピクセル処理とアクセス
私たちはアルゴリズムを処理し、特定のイメージを理解していれば、画像処理のために、我々はピクセルの画像を直接操作することによって、これらのアルゴリズムを実装することができるようになります。したがって、この記事では、いくつかの知識OpenCVのピクセル処理及びアクセスを要約します。
記事のディレクトリ
1.カラースペースの削減
1.1カラースペースの必要性が減少しました
画像の性質は、ピクセルは、一つから構成され、行列です。保存された画像データは、巨大なスペースを取る傾向にあります。シングルチャネル白黒画像場合、0-255番号の各画素は256色を表現します。そして、それは3チャンネルカラー画像である場合、各ピクセルは間違いなくオーバーヘッドペンのための巨大なデータ記憶装置である256x256x256可能な色を有することになります。
色空間の減少した場合、効果的にデータストレージの圧力を減らすことができます。私たちの方法は、色空間を減らし、色で近似することができます。例えば、チャネル256色:0-10のように表さ0、11-20として表さ1 ...というように、我々はこれだけ、3チャンネルのカラーマップのために、チャンネルの色を表現するために26桁が必要より客観的に格納圧縮比256x256x256に減少26x26x26。
この色を達成するためにどのようにそれを近似しますか?Cにおけるカットオフ分割機能の小数点以下の桁を有する++、int型、このように、色空間処理は、次の式がよいです
例:
Iold = 23は、次に、= 23/10 * 10 = Inewで
カラースペースを減らすために1.2ルックアップテーブル法
しかし、すべてのピクセルは、同様の計算を行うために持っているだけでなく、計算の膨大な量の場合。そこで、我々は、ルックアップテーブルのアイデアを使用するプロセスを簡素化することができます。あなたはすべての時間を計算する必要はありませんので、我々は、デジタル変換表にその対応後0から256までの記録を作成することができますが、変換テーブルを見つけることができます。
//查找表的创建
uchar table[256];
int divideWidth = 100;
for (int i = 0; i < 256; i++)
{
table[i] = i / divideWidth*divideWidth;
}
その後、画像は、各画素をP [i]は、以下の変換が色空間を減少させることによって達成することができるされているものとします
p[i]=table[p[i]];
1.3 LUT機能
OpenCVのは、色空間圧縮のために使用されたルックアップテーブル関数LUT、に組み込まれました。その機能は次のように定義されています。
void LUT(InputArray src, InputArray lut, OutputArray dst);
最初の引数:入力画像
第二引数:ルックアップテーブル
3番目のパラメータは:出力画像は、
これら三つのパラメータは、マットのタイプであるタイプ
使用例
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
int main()
{
//创建数值表
uchar table[256];
int dividedValue = 100;
for (int i = 0; i < 256; i++)
{
table[i] = i / dividedValue * dividedValue;
}
//定义图片
Mat srcImg, lut, dstImg;
srcImg = imread("1.png");
//创建查找表
lut.create(1, 256, CV_8UC1); //查找表一个通道就可以,处理三通道图片的时候,会把三个通道都安装lut的规则进行变换
uchar* p = lut.data;
for (int i = 0; i < 256; i++)
{
p[i] = table[i];
}
//查找表函数
imshow("a", srcImg);
LUT(srcImg, lut, dstImg);
imshow("b", dstImg);
waitKey(0);
}
2.動作効率決意プログラム
画像処理は、画像処理アルゴリズムの動作効率を理解する必要があり、これは番組の時間を実行することによって決定することができ、二つのそのような機能があります。
double getTickFrequency();//指示1秒钟CPU能够运行多少个周期
int64 getTickCount(); //用来判断cpu当前的运行周期
次のようにこの2つの機能とは、例えば、プログラムの実行中の時間を決定することができます。
double t1=(double)getTickCount();
//do something
t1 = ((double)getTickCount()-t1)/getTickFrequency();
cout << t1 << endl;
前記画像内の画素にアクセスする方法
3.1ポインタ
最速、しかし、ポインタ自体が危険な性質を有する:ピクセルにアクセスすることにより、ポインタ機能することです。
次のように言葉を選びました:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void colorReduce(Mat& srcImg, Mat& dstImg, int dividedValue)
{
//创建查找表
char table[256];
for (int i = 0; i < 256; i++)
{
table[i] = i / dividedValue * dividedValue;
}
//记录图片数据
int row = srcImg.rows;
int col = srcImg.cols;
int channel = srcImg.channels();
srcImg.copyTo(dstImg);
//使用指针的方法访问像素
for (int i = 0; i < row; i++)
{
uchar* p = dstImg.ptr<uchar>(i); //ptr是mat类的一个模板函数,返回值是第i行的头指针,尖括号里放的是返回值类型
for (int j = 0; j < col * channel; j++)
{
p[j] = table[p[j]];
}
}
}
int main()
{
Mat srcImg, dstImg;
srcImg = imread("1.png");
srcImg.copyTo(dstImg);
imshow("a", dstImg);
colorReduce(srcImg, dstImg, 100);
imshow("b", dstImg);
waitKey(0);
}
3.2イテレータ
画素のみの最初の画像とのピクセルを横切ることができる最後の画素アドレスのアドレスを知っている必要があります:それはイテレータアクセス画素が備えられています。操作は非常に簡単であり、それは安全ですので、何もオフサイドのメモリの問題はありません。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void colorReduce(Mat& srcImg, Mat& dstImg, int dividedValue)
{
//创建查找表
char table[256];
for (int i = 0; i < 256; i++)
{
table[i] = i / dividedValue * dividedValue;
}
//记录图片数据
int row = srcImg.rows;
int col = srcImg.cols;
int channel = srcImg.channels();
srcImg.copyTo(dstImg);
switch (channel)
{
//处理单通道的灰色图
case 1:
{
MatIterator_<uchar> it, end;//创建迭代器
for (it = dstImg.begin<uchar>(), end = dstImg.end<uchar>(); it != end; it++)
{
(*it) = table[(*it)];
}
break;
}
//处理三通道的彩色图
case 3:
{
cv::Mat_<cv::Vec3b>::iterator it = dstImg.begin<Vec3b>();//创建迭代器
cv::Mat_<cv::Vec3b>::iterator end = dstImg.end<Vec3b>();
for (; it != end; it++)
{
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
break;
}
}
}
int main()
{
Mat srcImg, dstImg;
srcImg = imread("1.png");
srcImg.copyTo(dstImg);
imshow("a", dstImg);
colorReduce(srcImg, dstImg, 100);
imshow("b", dstImg);
waitKey(0);
}
ここでは、それ以外の場合はエラーになり、変数を定義した場合のステートメントは、{}を追加してくださいという問題に注意を払う必要があります
3.3ダイナミック住所
マットクラスでの動的メモリ使用量がによって特徴付けられる:直感的な、非常に簡単にランクの値があることがわかる
次のように言葉を選びました:
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;
void colorReduce(Mat& srcImg, Mat& dstImg, int dividedValue)
{
//创建查找表
char table[256];
for (int i = 0; i < 256; i++)
{
table[i] = i / dividedValue * dividedValue;
}
//记录图片数据
int row = srcImg.rows;
int col = srcImg.cols;
int channel = srcImg.channels();
srcImg.copyTo(dstImg);
switch (channel)
{
//处理单通道的灰色图
case 1:
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
dstImg.at<uchar>(i, j) = table[dstImg.at<uchar>(i, j)];
}
}
break;
}
//处理三通道的彩色图
case 3:
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
dstImg.at<Vec3b>(i, j)[0] = table[dstImg.at<Vec3b>(i, j)[0]];
dstImg.at<Vec3b>(i, j)[1] = table[dstImg.at<Vec3b>(i, j)[1]];
dstImg.at<Vec3b>(i, j)[2] = table[dstImg.at<Vec3b>(i, j)[2]];
}
}
break;
}
}
}
int main()
{
Mat srcImg, dstImg;
srcImg = imread("1.png");
srcImg.copyTo(dstImg);
imshow("a", dstImg);
colorReduce(srcImg, dstImg, 100);
imshow("b", dstImg);
waitKey(0);
}
リファレンス
OpenCVの2つの研究ノート(スキャン画像)[1] https://blog.csdn.net/jameshater/article/details/50756729
[2]トークのOpenCVのルックアップテーブルLUT関数のルックアップテーブルのhttps://blog.csdn。ネット/ jameshater /記事/詳細/ 50759650?は、utm_source = blogxgwz8