いかおです。
前回の「プレモルの宣伝でやってるエフェクトを真似して」の続きです。
一つ一つのピクセルがuyvy422でくるとなると、hueへの変換は以下の様になります
まず、RGBにします。
R = 1.000Y + 1.402V
G = 1.000Y – 0.344U – 0.714V
B = 1.000Y + 1.772U
hue = 180 / π * atan2(√3 * (G – B), 2 * R – (float)G – B)
※double atan2(double y, double x); // math.h のやつね
これでHueがマイナスである場合がありますので、マイナスだったら
360を足します
これでやうやくHueになります。
こんな計算を例えば(たかだか)1080iでやろうとすると
毎秒この計算を、1920x1080x30 回やりますとかなりゴーヂャスなPCでも間に合いません
確かにこのままやったら再生が間に合わなかった
で、最初に全パターン計算しといてテーブルに格納するんです
マッチングテーブルですねぇ・・・
ただ、yuv値ってそれぞれ(この場合)8bitですが、実際の値の範囲は
| y | 16~235 |
| u(cb)/ v(cr) | 16~240 |
こんな感じになりますが、とりあえず全部作っちゃえってんで、ソースコード公開!!
★RGB全パターンからHueを求めてYUVのテーブルに押し込みます。
.
#define KOSUU 256
.
.
memset((char *)YUVTable, 0x00, sizeof(uint16_t) * KOSUU * KOSUU * KOSUU);
double root3 = sqrt(3);
float hue;
for(int ir=0;ir < KOSUU;ir++){
for(int ig=0;ig < KOSUU;ig++){
for(int ib=0;ib < KOSUU;ib++){
float y, u, v;
uint8_t ucy, ucu, ucv;
y = (0.299f * ir) + (0.577f * ig) + (0.114f * ib);
u = (-0.169f * ir) - (0.331f * ig) + (0.5f * ib);
v = (0.5f * ir) - (0.419f * ig) - (0.081f * ib);
if((round(y) < 0.0f) || (round(y) > 255.0f)){
syslog(LOG_ERR, "Y overfloow at(%d:%d:%d)", ir, ig, ib);
continue;
}
if((ir == 0) && (ig == 0) && (ib == 255)){
u = 255.0f;
} else if((round(u + 128.0f) < 0.0f) || (round(u + 128.0f) > 255.0f)){
syslog(LOG_ERR, "U overfloow at(%d:%d:%d)", ir, ig, ib);
continue;
}
if((ir == 255) && (ig == 0) && (ib == 0)){
v = 255.0f;
} else if((round(v + 128.0f) < 0.0f) || (round(v + 128.0f) > 255.0f)){
syslog(LOG_ERR, "V overfloow at(%d:%d:%d)", ir, ig, ib);
continue;
}
ucy = (uint8_t)round(y);
ucu = (uint8_t)round(u + 128.0f);
ucv = (uint8_t)round(v + 128.0f);
hue = 180 / M_PI * atan2(root3 * ((float)ig - (float)ib), 2 * (float)ir - (float)ig - (float)ib);
if(hue < 0.0f) hue = hue + 360;
YUVTable[(ucy * KOSUU * KOSUU) + (ucu * KOSUU) + ucv] = (uint16_t)round(hue);
}
}
}
これを、Hue中央値とレンジを指定させといて、比較のため”0″変位に置き換えて
// m_hue ..中央値
// m_range ..レンジ
// m_gap ..変位値(0変位比較のための加算する値)
// こんな風にしといて
if((m_hue + m_range) > 360)
m_high = (m_hue + m_range) - 360;
else
m_high = m_hue + m_range;
if(((int)m_hue - (int)m_range) < 0)
m_low = ((int)m_hue - (int)m_range) + 360;
else
m_low = m_hue - m_range; if(m_low > m_high){
m_gap = 360 - m_low;
m_low = 0;
m_high = m_high + m_gap;
......
uint16_t nowHue = YUVTable[(y * KOSU * KOSU) + (u * KOSU) + v] + m_gap;
if(nowHue > 360) nowHue = nowHue - 360;
if((nowHue <= m_low) || (nowHue >= m_high)){
// モノ黒にする
}
で、前回のサンプルでもいまいちキレイじゃないので、調査の上、
キレイにして掲載します(いずれね)





