6

色深度スケーリングを使用して減色を実行したいと思います。

この例のように: ここに画像の説明を入力

最初の画像は CGA 解像度、2 番目は EGA、3 番目は HAM です。cv::LUT でやりたいのですが、それがより良い方法だと思うからです。私はこのコードでグレースケールを行うことができます:

Mat img = imread("test1.jpg", 0);
uchar* p;
Mat lookUpTable(1, 256, CV_8U);
p = lookUpTable.data;
for( int i = 0; i < 256; ++i)
    p[i] = 16 * (i/16)
LUT(img, lookUpTable, reduced);

オリジナル:ここに画像の説明を入力

減色:ここに画像の説明を入力

しかし、色でやろうとすると、奇妙な結果が得られます..

ここに画像の説明を入力

このコードで:

imgColor = imread("test1.jpg");
Mat reducedColor;
int n = 16;
for (int i=0; i<256; i++) {
    uchar value = floor(i/n) * n;
    cout << (int)value << endl;
    lut.at<Vec3b>(i)[2]= (value >> 16) & 0xff;
    lut.at<Vec3b>(i)[1]= (value >> 8) & 0xff;
    lut.at<Vec3b>(i)[0]= value & 0xff;
} 
LUT(imgColor, lut, reducedColor);
4

2 に答える 2

3

おそらく今では先に進んでいるでしょうが、問題の根本は、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;
}
于 2013-12-25T00:12:17.310 に答える
0

iとはどちらnも整数なので、i/nは整数です。(double)i/nおそらく、床を取って を掛ける前に double() に変換したいnですか?

于 2013-02-11T13:05:17.910 に答える