Мне нужен более эффективный метод рисования прозрачной линии на изображении. С текущими функциями линии OpenCV производительность значительно ниже, чем хотелось бы. Похоже, медлительность связана с необходимостью клонировать и перезаписывать изображение в цикле. К сожалению, функция line не принимает альфа-значение напрямую, что затрудняет прямую реализацию. Я предпочитаю продолжать использовать функцию line из OpenCV из-за ее встроенной возможности сглаживания, но я открыт для изучения альтернативных решений, если они доступны.
Текущее медленное решение
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)));
Возможное решение №2?:
Может быть, одно из решений моей проблемы — чтобы добавить альфа-канал в исходный код функции line. Я пытался это сделать, но у меня не получается. И, честно говоря, код для меня слишком сложен. По крайней мере на данный момент
Вот исходный код функции, обрабатывающей рисование линий со сглаживанием. Я отметил /Идет сюда/, какая часть кода вызывается, чтобы было легче отслеживать.
Из моего тестирования я заменил пример 1 (исходный) на пример 2. Строка будет быть нарисовано с прозрачностью.
Но, конечно, с неправильным цветом и т. д. Но, с моей точки зрения, это говорит о том, что добавление альфа-канала должно быть возможным. Но как?
//Exsample 1 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; \
}
//exsample 2 color//The line will be transparent with color : Scalar(0, 255, 0, 100/*Doesn't change anything*/)
#define ICV_PUT_POINT() \
{ \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((0/*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; \
}
//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
}
}
Обновление 13.05.24
Я провел небольшое тестирование.
Я создал «Возможное решение №» .1?:". Он по-прежнему слишком медленный.
Он примерно в 3 раза быстрее, но все равно очень медленный.
Я также пытался работать над «Возможным решением № 2?:».Кажется, я правильно рисую линию и т. д.
Но я чувствую, что что-то не так. Но, похоже, я пока не могу понять, что именно.
Потому что я делаю некоторые расчеты интенсивности пикселей, которые изменятся после рисования линии. И я получаю результат, отличный от приведенного ниже кода и «Текущего медленного решения».
Вот мой текущий измененный код для «Возможного решения № 2?:»Рисование 1000 линий =
Альфа 1,54084 секунды
Без альфа (функция стандартной линии) 0,0763387 секунд
//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));
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;
}
//Calculate colors
#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; \
\
PixelData LinePixelData; \
LinePixelData.Coordinates = cv::Point2i((tptr - img.data) % img.step / img.elemSize(), (tptr - img.data) / img.step); \
LinePixelData.Color = cv::Vec4b(_cb, _cg, _cr, _ca); \
LineData.push_back(LinePixelData); \
}
//This dident work
//#define ICV_PUT_POINT() \
// { \
// _cb = tptr[0]; \
// _cg = tptr[1]; \
// _cr = tptr[2]; \
// _ca = tptr[3]; \
// tptr[0] = saturate_cast(_cb * Opacity + (_cb + (((cb - _cb) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[1] = saturate_cast(_cg * Opacity + (_cg + (((cg - _cg) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[2] = saturate_cast(_cr * Opacity + (_cr + (((cr - _cr) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[3] = saturate_cast(_ca * Opacity + (_ca + (((ca - _ca) * a + 127) >> 8)) * (1.0 - Opacity));\
// }
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;
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
for (size_t LinePixelsCount = 0; LinePixelsCount < LineData.size(); ++LinePixelsCount)
{
cv::Vec4b& img_Color = img.at(LineData[LinePixelsCount].Coordinates.y, LineData[LinePixelsCount].Coordinates.x);
cv::Vec4b& Line_Color = LineData[LinePixelsCount].Color;
for (int c = 0; c < 4; ++c)
{
img_Color[c] = saturate_cast(img_Color[c] * Opacity + Line_Color[c] * (1.0 - Opacity));
}
//cv::addWeighted(img_Color, Opacity, Line_Color, 1.0 - Opacity, 0.0, img_Color);
}
return true;
}
Как сравнивать методы «Текущее медленное решение» и «Возможное решение № 2?: Обновление 13.05.24 (пользовательская функция рисования линии)».
Мы видим, что мы в итоге цвет пикселей будет немного другим.
pos y 1 : 220
pos x 2 : 157
Color 1 : 130, 130, 130, 144
Color 2 : 146, 146, 146, 126
Color added together 1 : 133
Color added together 2 : 141
Подробнее здесь: https://stackoverflow.com/questions/783 ... in-opencvc
Эффективное рисование линии со значением альфа в OpenCV (С++) ⇐ C++
Программы на C++. Форум разработчиков
-
Anonymous
1715614518
Anonymous
Мне нужен более эффективный метод рисования прозрачной линии на изображении. С текущими функциями линии OpenCV производительность значительно ниже, чем хотелось бы. Похоже, медлительность связана с необходимостью клонировать и перезаписывать изображение в цикле. К сожалению, функция line не принимает альфа-значение напрямую, что затрудняет прямую реализацию. Я предпочитаю продолжать использовать функцию line из OpenCV из-за ее встроенной возможности сглаживания, но я открыт для изучения альтернативных решений, если они доступны.
[b]Текущее медленное решение[/b]
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);
[b]Я придумал несколько возможных решений.[/b]
[b]Возможное решение № 1? :[/b]
Решением ускорить код является реализация чего-то подобного.
Но нам нужно будет найти способ найти соседние пиксели, так что толщину также можно скорректировать. Я считаю, что это значительно ускорит процесс.
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)));
[b]Возможное решение №2?:[/b]
Может быть, одно из решений моей проблемы — чтобы добавить альфа-канал в исходный код функции line. Я пытался это сделать, но у меня не получается. И, честно говоря, код для меня слишком сложен. По крайней мере на данный момент
Вот исходный код функции, обрабатывающей рисование линий со сглаживанием. Я отметил /Идет сюда/, какая часть кода вызывается, чтобы было легче отслеживать.
Из моего тестирования я заменил пример 1 (исходный) на пример 2. Строка будет быть нарисовано с прозрачностью.
Но, конечно, с неправильным цветом и т. д. Но, с моей точки зрения, это говорит о том, что добавление альфа-канала должно быть возможным. Но как?
//Exsample 1 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; \
}
//exsample 2 color//The line will be transparent with color : Scalar(0, 255, 0, 100/*Doesn't change anything*/)
#define ICV_PUT_POINT() \
{ \
_cb = tptr[0]; \
_cb += ((cb - _cb)*a + 127)>> 8;\
_cg = tptr[1]; \
_cg += ((0/*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; \
}
//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
}
}
[b]Обновление 13.05.24[/b]
Я провел небольшое тестирование.
Я создал «Возможное решение №» .1?:". Он по-прежнему слишком медленный.
Он примерно в 3 раза быстрее, но все равно очень медленный.
Я также пытался работать над «Возможным решением № 2?:».Кажется, я правильно рисую линию и т. д.
Но я чувствую, что что-то не так. Но, похоже, я пока не могу понять, что именно.
Потому что я делаю некоторые расчеты интенсивности пикселей, которые изменятся после рисования линии. И я получаю результат, отличный от приведенного ниже кода и «Текущего медленного решения».
Вот мой текущий измененный код для «Возможного решения № 2?:»Рисование 1000 линий =
Альфа 1,54084 секунды
Без альфа (функция стандартной линии) 0,0763387 секунд
//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));
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;
}
//Calculate colors
#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; \
\
PixelData LinePixelData; \
LinePixelData.Coordinates = cv::Point2i((tptr - img.data) % img.step / img.elemSize(), (tptr - img.data) / img.step); \
LinePixelData.Color = cv::Vec4b(_cb, _cg, _cr, _ca); \
LineData.push_back(LinePixelData); \
}
//This dident work
//#define ICV_PUT_POINT() \
// { \
// _cb = tptr[0]; \
// _cg = tptr[1]; \
// _cr = tptr[2]; \
// _ca = tptr[3]; \
// tptr[0] = saturate_cast(_cb * Opacity + (_cb + (((cb - _cb) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[1] = saturate_cast(_cg * Opacity + (_cg + (((cg - _cg) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[2] = saturate_cast(_cr * Opacity + (_cr + (((cr - _cr) * a + 127) >> 8)) * (1.0 - Opacity));\
// tptr[3] = saturate_cast(_ca * Opacity + (_ca + (((ca - _ca) * a + 127) >> 8)) * (1.0 - Opacity));\
// }
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;
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
for (size_t LinePixelsCount = 0; LinePixelsCount < LineData.size(); ++LinePixelsCount)
{
cv::Vec4b& img_Color = img.at(LineData[LinePixelsCount].Coordinates.y, LineData[LinePixelsCount].Coordinates.x);
cv::Vec4b& Line_Color = LineData[LinePixelsCount].Color;
for (int c = 0; c < 4; ++c)
{
img_Color[c] = saturate_cast(img_Color[c] * Opacity + Line_Color[c] * (1.0 - Opacity));
}
//cv::addWeighted(img_Color, Opacity, Line_Color, 1.0 - Opacity, 0.0, img_Color);
}
return true;
}
Как сравнивать методы «Текущее медленное решение» и «Возможное решение № 2?: Обновление 13.05.24 (пользовательская функция рисования линии)».
Мы видим, что мы в итоге цвет пикселей будет немного другим.
pos y 1 : 220
pos x 2 : 157
Color 1 : 130, 130, 130, 144
Color 2 : 146, 146, 146, 126
Color added together 1 : 133
Color added together 2 : 141
Подробнее здесь: [url]https://stackoverflow.com/questions/78300673/efficiently-drawing-a-line-with-alpha-value-in-opencvc[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия