Текущее медленное решение
Код: Выделить всё
Mat Temp_overlay = inputImage.clone();
line(Temp_overlay, startPoint, endPoint, Scalar(255, 255, 255 /*, 100 Dont take alpha value*/), thickness, LINE_AA);
addWeighted(inputImage, opacity, Temp_overlay , 1.0 - opacity, 0.0, inputImage);
Возможное решение № 1? :
Решением ускорить код является реализация чего-то подобного.
Но нам нужно будет найти способ найти соседние пиксели, так что толщину также можно скорректировать. Я считаю, что это значительно ускорит процесс.
Код: Выделить всё
Mat Temp_overlay = inputImage.clone();
line(Temp_overlay, startPoint, endPoint, Scalar(255, 255, 255 /*, 100 Dont take alpha value*/), thickness, LINE_AA);
addWeighted(inputImage(Rect(startPoint, endPoint)), opacity,
Temp_overlay(Rect(startPoint, endPoint)), 1.0 - opacity, 0.0, inputImage(Rect(startPoint, endPoint)));
Возможно, одно из решений моей проблемы — чтобы добавить альфа-канал в исходный код функции line. Я пытался это сделать, но у меня не получается. И, честно говоря, код для меня слишком сложен. По крайней мере на данный момент
Вот исходный код функции, обрабатывающей рисование линий со сглаживанием.
Код: Выделить всё
//Full function code
static void
LineAA(Mat& img, Point2l pt1, Point2l pt2, const void* color)
{
int64 dx, dy;
int ecount, scount = 0;
int slope;
int64 ax, ay;
int64 x_step, y_step;
int64 i, j;
int ep_table[9];
int cb = ((uchar*)color)[0], cg = ((uchar*)color)[1], cr = ((uchar*)color)[2], ca = ((uchar*)color)[3];
int _cb, _cg, _cr, _ca;
int nch = img.channels();
uchar* ptr = img.ptr();
size_t step = img.step;
Size2l size(img.size());
if (!((nch == 1 || nch == 3 || nch == 4) && img.depth() == CV_8U))
{
Line(img, Point((int)(pt1.x >> XY_SHIFT), (int)(pt1.y >> XY_SHIFT)), Point((int)(pt2.x >> XY_SHIFT), (int)(pt2.y >> XY_SHIFT)), color);
return;
}
pt1.x -= XY_ONE * 2;
pt1.y -= XY_ONE * 2;
pt2.x -= XY_ONE * 2;
pt2.y -= XY_ONE * 2;
ptr += img.step * 2 + 2 * nch;
size.width = ((size.width - 5) XY_SHIFT) - (pt1.x >> XY_SHIFT));
j = -(pt1.x & (XY_ONE - 1));
pt1.y += ((y_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
slope = (y_step >> (XY_SHIFT - 5)) & 0x3f;
slope ^= (y_step < 0 ? 0x3f : 0);
/* Get 4-bit fractions for end-point adjustments */
i = (pt1.x >> (XY_SHIFT - 7)) & 0x78;
j = (pt2.x >> (XY_SHIFT - 7)) & 0x78;
}
else
{
dx = (dx ^ i) - i;
pt1.x ^= pt2.x & i;
pt2.x ^= pt1.x & i;
pt1.x ^= pt2.x & i;
pt1.y ^= pt2.y & i;
pt2.y ^= pt1.y & i;
pt1.y ^= pt2.y & i;
x_step = (dx > XY_SHIFT) - (pt1.y >> XY_SHIFT));
j = -(pt1.y & (XY_ONE - 1));
pt1.x += ((x_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
slope ^= (x_step < 0 ? 0x3f : 0);
/* Get 4-bit fractions for end-point adjustments */
i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
}
slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope];
/* Calc end point correction table */
{
int t0 = slope > 8) & 0x1ff;
ep_table[2] = (t1 >> 8) & 0x1ff;
ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
ep_table[6] = (t2 >> 8) & 0x1ff;
ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
}
if (nch == 3)
{
#define ICV_PUT_POINT() \
{ \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \
tptr[1] = (uchar)_cg; \
tptr[2] = (uchar)_cr; \
}
if (ax > ay)
{
ptr += (pt1.x >> XY_SHIFT) * 3;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr += 3;
scount++;
ecount--;
}
}
else
{
ptr += (pt1.y >> XY_SHIFT) * step;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 3;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += 3;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += 3;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
}
}
#undef ICV_PUT_POINT
}
else if (nch == 1)
{
#define ICV_PUT_POINT() \
{ \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \
}
if (ax > ay)
{
ptr += (pt1.x >> XY_SHIFT);
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr++;
scount++;
ecount--;
}
}
else
{
ptr += (pt1.y >> XY_SHIFT) * step;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.x >> XY_SHIFT) - 1);
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr++;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr++;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
}
}
#undef ICV_PUT_POINT
}
else
{
//color
#define ICV_PUT_POINT() \
{ \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((cg - _cg)*a + 127)>> 8;\
_cr = tptr[2]; \
_cr += ((cr - _cr)*a + 127)>> 8;\
_ca = tptr[3]; \
_ca += ((ca - _ca)*a + 127)>> 8;\
tptr[0] = (uchar)_cb; \
tptr[1] = (uchar)_cg; \
tptr[2] = (uchar)_cr; \
tptr[3] = (uchar)_ca; \
}
if (ax > ay)
{
/*Goes here*/
ptr += (pt1.x >> XY_SHIFT) * 4;
while (ecount >= 0)
{
/*Goes here*/
uchar* tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.y += y_step;
ptr += 4;
scount++;
ecount--;
}
}
else
{
ptr += (pt1.y >> XY_SHIFT) * step;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 4;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += 4;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
tptr += 4;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
ICV_PUT_POINT();
ICV_PUT_POINT();
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
}
}
#undef ICV_PUT_POINT
}
}
Мне удалось создать решение на основе «Возможного решения № 2?: ". И я скажу, что скорость хорошая. Но я оставлю этот вопрос открытым еще немного, если у кого-то найдется еще лучшее решение.
Я также создал «Возможное решение № 1?:». Это по-прежнему было слишком медленно.
Это было примерно в 3 раза быстрее, чем «Текущее медленное решение», но все равно очень медленно.
Скорость рисования 1000 линий =
Нормальная линия без альфы: 0,0763387 секунды,Оригинальное решение: 745,123 секунды.
Функция пользовательской линии с альфа-каналом: 0,291911 секунды.
Код: Выделить всё
//Modified function from OpenCV LineAA
bool ScalarToRawData(const Scalar& s, void* _buf, int type, int unroll_to)
{
int i, depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
CV_Assert(cn XY_SHIFT) - (pt1.y >> XY_SHIFT));
j = -(pt1.y & (XY_ONE - 1));
pt1.x += ((x_step * j) >> XY_SHIFT) + (XY_ONE >> 1);
slope = (x_step >> (XY_SHIFT - 5)) & 0x3f;
slope ^= (x_step < 0 ? 0x3f : 0);
/* Get 4-bit fractions for end-point adjustments */
i = (pt1.y >> (XY_SHIFT - 7)) & 0x78;
j = (pt2.y >> (XY_SHIFT - 7)) & 0x78;
}
slope = (slope & 0x20) ? 0x100 : SlopeCorrTable[slope];
/* Calc end point correction table */
{
int t0 = slope > 8) & 0x1ff;
ep_table[2] = (t1 >> 8) & 0x1ff;
ep_table[4] = ((((j - i) + 0x80) | 4) * slope >> 8) & 0x1ff;
ep_table[5] = ((t1 + t0) >> 8) & 0x1ff;
ep_table[6] = (t2 >> 8) & 0x1ff;
ep_table[7] = ((t2 + t0) >> 8) & 0x1ff;
}
if (ax > ay)
{
ptr += (pt1.x >> XY_SHIFT) * 4;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.y >> XY_SHIFT) - 1) * step;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.y >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
//If you want to store coordinates, you can do this : cv::Point2i Coordinates = cv::Point2i((tptr - img.data) % img.step / img.elemSize(), (tptr - img.data) / img.step);
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
tptr += step;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
tptr += step;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
pt1.y += y_step;
ptr += 4;
scount++;
ecount--;
}
}
else
{
ptr += (pt1.y >> XY_SHIFT) * step;
while (ecount >= 0)
{
uchar* tptr = ptr + ((pt1.x >> XY_SHIFT) - 1) * 4;
int ep_corr = ep_table[(((scount >= 2) + 1) & (scount | 2)) * 3 +
(((ecount >= 2) + 1) & (ecount | 2))];
int a, dist = (pt1.x >> (XY_SHIFT - 5)) & 31;
a = (ep_corr * FilterTable[dist + 32] >> 8) & 0xff;
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
tptr += 4;
a = (ep_corr * FilterTable[dist] >> 8) & 0xff;
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
tptr += 4;
a = (ep_corr * FilterTable[63 - dist] >> 8) & 0xff;
_cb = tptr[0];
_cb += ((cb - _cb) * a + 127) >> 8;
_cb += ((cb - _cb) * a + 127) >> 8;
_cg = tptr[1];
_cg += ((cg - _cg) * a + 127) >> 8;
_cg += ((cg - _cg) * a + 127) >> 8;
_cr = tptr[2];
_cr += ((cr - _cr) * a + 127) >> 8;
_cr += ((cr - _cr) * a + 127) >> 8;
_ca = tptr[3];
_ca += ((ca - _ca) * a + 127) >> 8;
_ca += ((ca - _ca) * a + 127) >> 8;
tptr[0] = saturate_cast(tptr[0] * Opacity + _cb * (1.0 - Opacity));
tptr[1] = saturate_cast(tptr[1] * Opacity + _cg * (1.0 - Opacity));
tptr[2] = saturate_cast(tptr[2] * Opacity + _cr * (1.0 - Opacity));
tptr[3] = saturate_cast(tptr[3] * Opacity + _ca * (1.0 - Opacity));
pt1.x += x_step;
ptr += step;
scount++;
ecount--;
}
}
return true;
Подробнее здесь: https://stackoverflow.com/questions/783 ... in-opencvc
Мобильная версия