おそらく今では先に進んでいるでしょうが、問題の根本は、uchar value
ちょうど 8 ビットの長さの に 16 ビットのシフトを行っていることです。この場合の 8 ビット シフトでも多すぎますuchar
。次に、ドキュメントには「8ビット要素の入力配列」でなければならないと明示的に記載されているという事実がcv::LUT
ありsrc
ますが、これは明らかにあなたのコードには当てはまりません。最終的な結果は、カラー イメージの最初のチャネル (青チャネル) のみが によって変換されることcv::LUT
です。
これらの制限を回避する最善の方法は、カラー イメージをチャネル間で分割し、各チャネルを個別に変換してから、変換されたチャネルを新しいカラー イメージに結合することです。以下のコードを参照してください。
/*
Calculates a table of 256 assignments with the given number of distinct values.
Values are taken at equal intervals from the ranges [0, 128) and [128, 256),
such that both 0 and 255 are always included in the range.
*/
cv::Mat lookupTable(int levels) {
int factor = 256 / levels;
cv::Mat table(1, 256, CV_8U);
uchar *p = table.data;
for(int i = 0; i < 128; ++i) {
p[i] = factor * (i / factor);
}
for(int i = 128; i < 256; ++i) {
p[i] = factor * (1 + (i / factor)) - 1;
}
return table;
}
/*
Truncates channel levels in the given image to the given number of
equally-spaced values.
Arguments:
image
Input multi-channel image. The specific color space is not
important, as long as all channels are encoded from 0 to 255.
levels
The number of distinct values for the channels of the output
image. Output values are drawn from the range [0, 255] from
the extremes inwards, resulting in a nearly equally-spaced scale
where the smallest and largest values are always 0 and 255.
Returns:
Multi-channel images with values truncated to the specified number of
distinct levels.
*/
cv::Mat colorReduce(const cv::Mat &image, int levels) {
cv::Mat table = lookupTable(levels);
std::vector<cv::Mat> c;
cv::split(image, c);
for (std::vector<cv::Mat>::iterator i = c.begin(), n = c.end(); i != n; ++i) {
cv::Mat &channel = *i;
cv::LUT(channel.clone(), table, channel);
}
cv::Mat reduced;
cv::merge(c, reduced);
return reduced;
}