Re[2]: профи или упоротый
От: jyuyjiyuijyu  
Дата: 19.02.15 05:31
Оценка: :)
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, jyuyjiyuijyu, Вы писали:


J>>goto? не, не слышал


A>Похоже, что как раз "слышал"

A>.. ибо с goto ситуация интересная:
A>1) Начинающий программист пишет код с goto по незнанию.
A>2) Продолжающий программист в курсе, что goto — моветон, и старается избежать
A>его любыми способами. Что мы и наблюдаем в данном случае.
A>3) Профессионал тоже избегает goto, только способы уже не "любые", а "изящные"

насчет профи очень спорно, гото очень много в ядре систем написанных на С
Re: профи или упоротый
От: pestis  
Дата: 19.02.15 06:04
Оценка: -3
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>goto? не, не слышал


Упоротый. Но гото тут не при чем. Только упопротый станет писать высокоуровневую обработку изображений на крестах. Ну или школьник, как вариант.
Re[3]: профи или упоротый
От: andy1618 Россия  
Дата: 19.02.15 09:13
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>>>goto? не, не слышал


A>>Похоже, что как раз "слышал"

A>>.. ибо с goto ситуация интересная:
A>>1) Начинающий программист пишет код с goto по незнанию.
A>>2) Продолжающий программист в курсе, что goto — моветон, и старается избежать
A>>его любыми способами. Что мы и наблюдаем в данном случае.
A>>3) Профессионал тоже избегает goto, только способы уже не "любые", а "изящные"

J>насчет профи очень спорно, гото очень много в ядре систем написанных на С



Да, мне тоже иногда приходится этот оператор использовать,
например, когда пишу что-нибудь для души на VBA для Excel — там для обработки
ошибок есть конструкция On Error GoTo <label>, альтернативы которой нет.
Re[2]: профи или упоротый
От: RiNSpy  
Дата: 19.02.15 09:38
Оценка: +1
Здравствуйте, andy1618, Вы писали:

A>Резюме:

A>Ни goto, ни break тут не нужны — нужна отдельная функция с return. Заодно и читабельность кода улучшится.
A>Ещё резануло глаз присутствие магических чисел (160, 11) — обычно это тоже признак п.1

По объективным параметрам код, конечно, плохой, но — нужно учитывать, для чего и в какой ситуации этот код писался:

если цель была написать код быстро, код будет использоваться один раз и не будет расти, им не будет больше никто пользоваться, то нормальный код. Например, при разбиении на функции, в данном случае читабельность кода может и упасть, просто потому что функции по порядку читать труднее, придётся прыгать из основного метода в вызываемые функции, чтобы понять, что там происходит.

Условия выхода из циклов тоже вполне читабельны.
Re: профи или упоротый
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 19.02.15 12:53
Оценка: +1
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>goto? не, не слышал

Тут наверное "Абстракции? Нет, не слышал."
Sic luceat lux!
Re[10]: профи или упоротый
От: dr. Acula Украина  
Дата: 19.02.15 18:51
Оценка:
__>Нормальные люди ... И если вдруг такое достанется, то просто выкинут на помойку, а не будут разбираться, ... Даже свое время тратить не будут на проверку этих вещей.

да, подход типичного "школоло", который "знает как надо делать, а остальные — дебилы".
Re[11]: профи или упоротый
От: __kot2  
Дата: 19.02.15 19:56
Оценка:
Здравствуйте, dr. Acula, Вы писали:
DA>да, подход типичного "школоло", который "знает как надо делать, а остальные — дебилы".
да нет, просто чем старше становишься, тем больше свое время ценить начинаешь
Re: профи или упоротый
От: VladFein США  
Дата: 19.02.15 20:59
Оценка: 12 (3) +5
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>goto? не, не слышал

J>тыц

А кроме вчетверо вложенного if(found) { break; } Вас ничего не смущает?
"Профессиональное" отрицание всякого рода венгерских нотаций, например? Находясь в самом вложенном цикле, как определить что перемменная xa локальная, а xout — член класса (или глобальная переменная)?
Analyse — это глагол, а не вопрос. Он не должен быть bool. Функция возвращает true если на картинке найдена цифра; может, назвать её HasDigit? Кроме того, вызывающую сторону не интересует — какая цифра была найдена? Раз мы-то знаем, может возвращать эту цифру, на всякий случай? Или -1 если не нашли?
После вызова этой функции, будет продолжен поиск следующей цифры? Начиная, опять, с преобразования в монохромный image?
В самом первом if(found) { break; }, мы знаем что цифра найдена, и имеем ВСЮ информацию для "Mark detected digit". Если сделать это сразу — переменные nr, deg и xout/yout можно не выводить за пределы цикла. Кроме того, функцию можно будет не прерывать, а продолжать искать следующие цифры прямо с этого места!
Функция Analyse (или HasDigit) должна бы быть const. Что это за разрушительный анализ?
Однобитный битмэп не обязательно держать в 24-битном. Я бы сделал bool monoImage[][], заодно повысил бы шансы поместиться в кэш. Это, кстати, упростит корявое условие if(!image->pixels[ya][xa][0] == 0x00). Вы в самом деле хотели сперва сделать bitwise NOT этому байту и потом сравнить с 0x00?
А это что делает: Select random point of digit? Забавный side effect? Он хотя бы документирован?
Меня также смущает число 160. Во-первых, почему 160? А во-вторых, почему одинаковое число для всех трёх цветов? Учитывая, что gray = 0.299R+0.587G+0.114B...
Re[2]: профи или упоротый
От: johny5 Новая Зеландия
Дата: 20.02.15 00:24
Оценка:
Здравствуйте, andy1618, Вы писали:

A>Здравствуйте, jyuyjiyuijyu, Вы писали:


J>>goto? не, не слышал


A>Похоже, что как раз "слышал"

A>.. ибо с goto ситуация интересная:
A>1) Начинающий программист пишет код с goto по незнанию.
A>2) Продолжающий программист в курсе, что goto — моветон, и старается избежать
A>его любыми способами. Что мы и наблюдаем в данном случае.
A>3) Профессионал тоже избегает goto, только способы уже не "любые", а "изящные"

У меня сложилось другое видение.
Начинающий и продолжающий программист никогда не напишет goto, потому что это запрещается.
Профессионал прищуривается.
Re[2]: профи или упоротый
От: velkin Удмуртия https://kisa.biz
Дата: 20.02.15 00:47
Оценка:
Здравствуйте, pestis, Вы писали:

P>Упоротый. Но гото тут не при чем. Только упопротый станет писать высокоуровневую обработку изображений на крестах. Ну или школьник, как вариант.


Ну или разработчики OpenCV как вариант.

/****************************************************************************************\
*                     Multi-Scale variant of Classical Hough Transform                   *
\****************************************************************************************/

//DECLARE_AND_IMPLEMENT_LIST( _index, h_ );
IMPLEMENT_LIST( _index, h_ )

static void
icvHoughLinesSDiv( const CvMat* img,
                   float rho, float theta, int threshold,
                   int srn, int stn,
                   CvSeq* lines, int linesMax )
{
    std::vector<uchar> _caccum, _buffer;
    std::vector<float> _sinTable;
    std::vector<int> _x, _y;
    float* sinTable;
    int *x, *y;
    uchar *caccum, *buffer;
    _CVLIST* list = 0;

#define _POINT(row, column)\
    (image_src[(row)*step+(column)])

    uchar *mcaccum = 0;
    int rn, tn;                 /* number of rho and theta discrete values */
    int index, i;
    int ri, ti, ti1, ti0;
    int row, col;
    float r, t;                 /* Current rho and theta */
    float rv;                   /* Some temporary rho value */
    float irho;
    float itheta;
    float srho, stheta;
    float isrho, istheta;

    const uchar* image_src;
    int w, h, step;
    int fn = 0;
    float xc, yc;

    const float d2r = (float)(Pi / 180);
    int sfn = srn * stn;
    int fi;
    int count;
    int cmax = 0;

    CVPOS pos;
    _index *pindex;
    _index vi;

    CV_Assert( CV_IS_MAT(img) && CV_MAT_TYPE(img->type) == CV_8UC1 );
    CV_Assert( linesMax > 0 && rho > 0 && theta > 0 );

    threshold = MIN( threshold, 255 );

    image_src = img->data.ptr;
    step = img->step;
    w = img->cols;
    h = img->rows;

    irho = 1 / rho;
    itheta = 1 / theta;
    srho = rho / srn;
    stheta = theta / stn;
    isrho = 1 / srho;
    istheta = 1 / stheta;

    rn = cvFloor( sqrt( (double)w * w + (double)h * h ) * irho );
    tn = cvFloor( 2 * Pi * itheta );

    list = h_create_list__index( linesMax < 1000 ? linesMax : 1000 );
    vi.value = threshold;
    vi.rho = -1;
    h_add_head__index( list, &vi );

    /* Precalculating sin */
    _sinTable.resize( 5 * tn * stn );
    sinTable = &_sinTable[0];

    for( index = 0; index < 5 * tn * stn; index++ )
        sinTable[index] = (float)cos( stheta * index * 0.2f );

    _caccum.resize(rn * tn);
    caccum = &_caccum[0];
    memset( caccum, 0, rn * tn * sizeof( caccum[0] ));

    /* Counting all feature pixels */
    for( row = 0; row < h; row++ )
        for( col = 0; col < w; col++ )
            fn += _POINT( row, col ) != 0;

    _x.resize(fn);
    _y.resize(fn);
    x = &_x[0];
    y = &_y[0];

    /* Full Hough Transform (it's accumulator update part) */
    fi = 0;
    for( row = 0; row < h; row++ )
    {
        for( col = 0; col < w; col++ )
        {
            if( _POINT( row, col ))
            {
                int halftn;
                float r0;
                float scale_factor;
                int iprev = -1;
                float phi, phi1;
                float theta_it;     /* Value of theta for iterating */

                /* Remember the feature point */
                x[fi] = col;
                y[fi] = row;
                fi++;

                yc = (float) row + 0.5f;
                xc = (float) col + 0.5f;

                /* Update the accumulator */
                t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
                r = (float) sqrt( (double)xc * xc + (double)yc * yc );
                r0 = r * irho;
                ti0 = cvFloor( (t + Pi / 2) * itheta );

                caccum[ti0]++;

                theta_it = rho / r;
                theta_it = theta_it < theta ? theta_it : theta;
                scale_factor = theta_it * itheta;
                halftn = cvFloor( Pi / theta_it );
                for( ti1 = 1, phi = theta_it - halfPi, phi1 = (theta_it + t) * itheta;
                     ti1 < halftn; ti1++, phi += theta_it, phi1 += scale_factor )
                {
                    rv = r0 * _cos( phi );
                    i = cvFloor( rv ) * tn;
                    i += cvFloor( phi1 );
                    assert( i >= 0 );
                    assert( i < rn * tn );
                    caccum[i] = (uchar) (caccum[i] + ((i ^ iprev) != 0));
                    iprev = i;
                    if( cmax < caccum[i] )
                        cmax = caccum[i];
                }
            }
        }
    }

    /* Starting additional analysis */
    count = 0;
    for( ri = 0; ri < rn; ri++ )
    {
        for( ti = 0; ti < tn; ti++ )
        {
            if( caccum[ri * tn + ti] > threshold )
            {
                count++;
            }
        }
    }

    if( count * 100 > rn * tn )
    {
        icvHoughLinesStandard( img, rho, theta, threshold, lines, linesMax );
        return;
    }

    _buffer.resize(srn * stn + 2);
    buffer = &_buffer[0];
    mcaccum = buffer + 1;

    count = 0;
    for( ri = 0; ri < rn; ri++ )
    {
        for( ti = 0; ti < tn; ti++ )
        {
            if( caccum[ri * tn + ti] > threshold )
            {
                count++;
                memset( mcaccum, 0, sfn * sizeof( uchar ));

                for( index = 0; index < fn; index++ )
                {
                    int ti2;
                    float r0;

                    yc = (float) y[index] + 0.5f;
                    xc = (float) x[index] + 0.5f;

                    /* Update the accumulator */
                    t = (float) fabs( cvFastArctan( yc, xc ) * d2r );
                    r = (float) sqrt( (double)xc * xc + (double)yc * yc ) * isrho;
                    ti0 = cvFloor( (t + Pi * 0.5f) * istheta );
                    ti2 = (ti * stn - ti0) * 5;
                    r0 = (float) ri *srn;

                    for( ti1 = 0 /*, phi = ti*theta - Pi/2 - t */ ; ti1 < stn; ti1++, ti2 += 5
                         /*phi += stheta */  )
                    {
                        /*rv = r*_cos(phi) - r0; */
                        rv = r * sinTable[(int) (abs( ti2 ))] - r0;
                        i = cvFloor( rv ) * stn + ti1;

                        i = CV_IMAX( i, -1 );
                        i = CV_IMIN( i, sfn );
                        mcaccum[i]++;
                        assert( i >= -1 );
                        assert( i <= sfn );
                    }
                }

                /* Find peaks in maccum... */
                for( index = 0; index < sfn; index++ )
                {
                    i = 0;
                    pos = h_get_tail_pos__index( list );
                    if( h_get_prev__index( &pos )->value < mcaccum[index] )
                    {
                        vi.value = mcaccum[index];
                        vi.rho = index / stn * srho + ri * rho;
                        vi.theta = index % stn * stheta + ti * theta - halfPi;
                        while( h_is_pos__index( pos ))
                        {
                            if( h_get__index( pos )->value > mcaccum[index] )
                            {
                                h_insert_after__index( list, pos, &vi );
                                if( h_get_count__index( list ) > linesMax )
                                {
                                    h_remove_tail__index( list );
                                }
                                break;
                            }
                            h_get_prev__index( &pos );
                        }
                        if( !h_is_pos__index( pos ))
                        {
                            h_add_head__index( list, &vi );
                            if( h_get_count__index( list ) > linesMax )
                            {
                                h_remove_tail__index( list );
                            }
                        }
                    }
                }
            }
        }
    }

    pos = h_get_head_pos__index( list );
    if( h_get_count__index( list ) == 1 )
    {
        if( h_get__index( pos )->rho < 0 )
        {
            h_clear_list__index( list );
        }
    }
    else
    {
        while( h_is_pos__index( pos ))
        {
            CvLinePolar line;
            pindex = h_get__index( pos );
            if( pindex->rho < 0 )
            {
                /* This should be the last element... */
                h_get_next__index( &pos );
                assert( !h_is_pos__index( pos ));
                break;
            }
            line.rho = pindex->rho;
            line.angle = pindex->theta;
            cvSeqPush( lines, &line );

            if( lines->total >= linesMax )
                break;
            h_get_next__index( &pos );
        }
    }

    h_destroy_list__index(list);
}
Re[3]: профи или упоротый
От: __kot2  
Дата: 20.02.15 01:16
Оценка:
Здравствуйте, velkin, Вы писали:
V>Ну или разработчики OpenCV как вариант.
ну ни для кого тут сокретом не являются, думаю, что многий продакшен код такие вот макароны написанные левой ногой.
просто большинство обычных людей это касается только когда в таком стиле пишут OpenSSL и потом удивлются, что там глк на глюке. а так то такой это только проблема товарищей из opencv как они этот код будут расширять, отлаживать или портировать. да и если весь opencv таквоц то судя по всему opencv работает только из-за компенсации багов друг другом и только ра малине девелоперов и только на их примерах
Re[3]: профи или упоротый
От: velkin Удмуртия https://kisa.biz
Дата: 20.02.15 01:47
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

MR>>а нафига там goto, если у каждого цикла уже есть выражение для остановки, куда этот found и можно засунуть


J>уже лучше но всё равно костыль, гото там то что доктор прописал


Согласен, причём в книжках по С++ не запрещают писать goto, просто говорится, что в большинстве случаев это плохая практика. Об исключениях почему-то те кто учился потом забывают. Но мне стало интересно, и я включил поиск по OpenCV, причём не считаю разработчиков топовых библиотек упоротыми, даже если в принципе можно написать лучше. И вот один из обнаруженных примеров, то есть goto применяется, когда это необходимо.

А так, конечно, пусть люди расскажут, как выйти из двух вложенных циклов, при этом не теряя время на проверку условий. Когда-то давно уже думал над этим вопросом, и ничего кроме goto в голову не пришло, разве что перестроить алгоритм, если это возможно так, чтобы не надо было выходить.

Что касается return, то тогда для оптимизации придётся писать inline. А это повлечёт за собой определение в заголовочном файле, пусть даже завуалировано. И нужно же понимать, что разные люди пишут по-разному и даже до меня со временем стало доходить, что мои объектно-ориентированные техники на самом деле инструменты аналитики, и писать в них иногда крайне неразумно.

Пожалуй лишь обобщённое программирование (шаблоны C++) не теряет скорости работы при различных аналитических извращениях, но и у них есть свой алгоритмический предел. Опять же есть желание разбить всё на части, ввести тысяча пятьсот абстракций, но опыт работы и общение с другими программистами говорит, что так делать не стоит, так как во многих случаях это заканчивается плохо.

Для разбиения функция должна иметь повторно используемые части, но где же им взяться, если проект мелкий. Вот тут и попадаем в ловушку, в которой сишники чувствуют себя хорошо, а все остальные не очень. Хотя по идее оптимальнее всего совмещать разные парадигмы в зависимости от обстоятельств.

void cv::Canny( InputArray _src, OutputArray _dst,
                double low_thresh, double high_thresh,
                int aperture_size, bool L2gradient )
{
    Mat src = _src.getMat();
    CV_Assert( src.depth() == CV_8U );

    _dst.create(src.size(), CV_8U);
    Mat dst = _dst.getMat();

    if (!L2gradient && (aperture_size & CV_CANNY_L2_GRADIENT) == CV_CANNY_L2_GRADIENT)
    {
        //backward compatibility
        aperture_size &= ~CV_CANNY_L2_GRADIENT;
        L2gradient = true;
    }

    if ((aperture_size & 1) == 0 || (aperture_size != -1 && (aperture_size < 3 || aperture_size > 7)))
        CV_Error(CV_StsBadFlag, "");

    if (low_thresh > high_thresh)
        std::swap(low_thresh, high_thresh);

#ifdef HAVE_TEGRA_OPTIMIZATION
    if (tegra::canny(src, dst, low_thresh, high_thresh, aperture_size, L2gradient))
        return;
#endif

#ifdef USE_IPP_CANNY
    if( aperture_size == 3 && !L2gradient &&
        ippCanny(src, dst, (float)low_thresh, (float)high_thresh) )
        return;
#endif

    const int cn = src.channels();
    Mat dx(src.rows, src.cols, CV_16SC(cn));
    Mat dy(src.rows, src.cols, CV_16SC(cn));

    Sobel(src, dx, CV_16S, 1, 0, aperture_size, 1, 0, cv::BORDER_REPLICATE);
    Sobel(src, dy, CV_16S, 0, 1, aperture_size, 1, 0, cv::BORDER_REPLICATE);

    if (L2gradient)
    {
        low_thresh = std::min(32767.0, low_thresh);
        high_thresh = std::min(32767.0, high_thresh);

        if (low_thresh > 0) low_thresh *= low_thresh;
        if (high_thresh > 0) high_thresh *= high_thresh;
    }
    int low = cvFloor(low_thresh);
    int high = cvFloor(high_thresh);

    ptrdiff_t mapstep = src.cols + 2;
    AutoBuffer<uchar> buffer((src.cols+2)*(src.rows+2) + cn * mapstep * 3 * sizeof(int));

    int* mag_buf[3];
    mag_buf[0] = (int*)(uchar*)buffer;
    mag_buf[1] = mag_buf[0] + mapstep*cn;
    mag_buf[2] = mag_buf[1] + mapstep*cn;
    memset(mag_buf[0], 0, /* cn* */mapstep*sizeof(int));

    uchar* map = (uchar*)(mag_buf[2] + mapstep*cn);
    memset(map, 1, mapstep);
    memset(map + mapstep*(src.rows + 1), 1, mapstep);

    int maxsize = std::max(1 << 10, src.cols * src.rows / 10);
    std::vector<uchar*> stack(maxsize);
    uchar **stack_top = &stack[0];
    uchar **stack_bottom = &stack[0];

    /* sector numbers
       (Top-Left Origin)

        1   2   3
         *  *  *
          * * *
        0*******0
          * * *
         *  *  *
        3   2   1
    */

    #define CANNY_PUSH(d)    *(d) = uchar(2), *stack_top++ = (d)
    #define CANNY_POP(d)     (d) = *--stack_top

    // calculate magnitude and angle of gradient, perform non-maxima supression.
    // fill the map with one of the following values:
    //   0 - the pixel might belong to an edge
    //   1 - the pixel can not belong to an edge
    //   2 - the pixel does belong to an edge
    for (int i = 0; i <= src.rows; i++)
    {
        int* _norm = mag_buf[(i > 0) + 1] + 1;
        if (i < src.rows)
        {
            short* _dx = dx.ptr<short>(i);
            short* _dy = dy.ptr<short>(i);

            if (!L2gradient)
            {
                for (int j = 0; j < src.cols*cn; j++)
                    _norm[j] = std::abs(int(_dx[j])) + std::abs(int(_dy[j]));
            }
            else
            {
                for (int j = 0; j < src.cols*cn; j++)
                    _norm[j] = int(_dx[j])*_dx[j] + int(_dy[j])*_dy[j];
            }

            if (cn > 1)
            {
                for(int j = 0, jn = 0; j < src.cols; ++j, jn += cn)
                {
                    int maxIdx = jn;
                    for(int k = 1; k < cn; ++k)
                        if(_norm[jn + k] > _norm[maxIdx]) maxIdx = jn + k;
                    _norm[j] = _norm[maxIdx];
                    _dx[j] = _dx[maxIdx];
                    _dy[j] = _dy[maxIdx];
                }
            }
            _norm[-1] = _norm[src.cols] = 0;
        }
        else
            memset(_norm-1, 0, /* cn* */mapstep*sizeof(int));

        // at the very beginning we do not have a complete ring
        // buffer of 3 magnitude rows for non-maxima suppression
        if (i == 0)
            continue;

        uchar* _map = map + mapstep*i + 1;
        _map[-1] = _map[src.cols] = 1;

        int* _mag = mag_buf[1] + 1; // take the central row
        ptrdiff_t magstep1 = mag_buf[2] - mag_buf[1];
        ptrdiff_t magstep2 = mag_buf[0] - mag_buf[1];

        const short* _x = dx.ptr<short>(i-1);
        const short* _y = dy.ptr<short>(i-1);

        if ((stack_top - stack_bottom) + src.cols > maxsize)
        {
            int sz = (int)(stack_top - stack_bottom);
            maxsize = maxsize * 3/2;
            stack.resize(maxsize);
            stack_bottom = &stack[0];
            stack_top = stack_bottom + sz;
        }

        int prev_flag = 0;
        for (int j = 0; j < src.cols; j++)
        {
            #define CANNY_SHIFT 15
            const int TG22 = (int)(0.4142135623730950488016887242097*(1<<CANNY_SHIFT) + 0.5);

            int m = _mag[j];

            if (m > low)
            {
                int xs = _x[j];
                int ys = _y[j];
                int x = std::abs(xs);
                int y = std::abs(ys) << CANNY_SHIFT;

                int tg22x = x * TG22;

                if (y < tg22x)
                {
                    if (m > _mag[j-1] && m >= _mag[j+1]) goto __ocv_canny_push;
                }
                else
                {
                    int tg67x = tg22x + (x << (CANNY_SHIFT+1));
                    if (y > tg67x)
                    {
                        if (m > _mag[j+magstep2] && m >= _mag[j+magstep1]) goto __ocv_canny_push;
                    }
                    else
                    {
                        int s = (xs ^ ys) < 0 ? -1 : 1;
                        if (m > _mag[j+magstep2-s] && m > _mag[j+magstep1+s]) goto __ocv_canny_push;
                    }
                }
            }
            prev_flag = 0;
            _map[j] = uchar(1);
            continue;
__ocv_canny_push:
            if (!prev_flag && m > high && _map[j-mapstep] != 2)
            {
                CANNY_PUSH(_map + j);
                prev_flag = 1;
            }
            else
                _map[j] = 0;
        }

        // scroll the ring buffer
        _mag = mag_buf[0];
        mag_buf[0] = mag_buf[1];
        mag_buf[1] = mag_buf[2];
        mag_buf[2] = _mag;
    }

    // now track the edges (hysteresis thresholding)
    while (stack_top > stack_bottom)
    {
        uchar* m;
        if ((stack_top - stack_bottom) + 8 > maxsize)
        {
            int sz = (int)(stack_top - stack_bottom);
            maxsize = maxsize * 3/2;
            stack.resize(maxsize);
            stack_bottom = &stack[0];
            stack_top = stack_bottom + sz;
        }

        CANNY_POP(m);

        if (!m[-1])         CANNY_PUSH(m - 1);
        if (!m[1])          CANNY_PUSH(m + 1);
        if (!m[-mapstep-1]) CANNY_PUSH(m - mapstep - 1);
        if (!m[-mapstep])   CANNY_PUSH(m - mapstep);
        if (!m[-mapstep+1]) CANNY_PUSH(m - mapstep + 1);
        if (!m[mapstep-1])  CANNY_PUSH(m + mapstep - 1);
        if (!m[mapstep])    CANNY_PUSH(m + mapstep);
        if (!m[mapstep+1])  CANNY_PUSH(m + mapstep + 1);
    }

    // the final pass, form the final image
    const uchar* pmap = map + mapstep + 1;
    uchar* pdst = dst.ptr();
    for (int i = 0; i < src.rows; i++, pmap += mapstep, pdst += dst.step)
    {
        for (int j = 0; j < src.cols; j++)
            pdst[j] = (uchar)-(pmap[j] >> 1);
    }
}
Re[4]: профи или упоротый
От: velkin Удмуртия https://kisa.biz
Дата: 20.02.15 02:15
Оценка: +1
Здравствуйте, __kot2, Вы писали:

__>Здравствуйте, velkin, Вы писали:

V>>Ну или разработчики OpenCV как вариант.
__>ну ни для кого тут сокретом не являются, думаю, что многий продакшен код такие вот макароны написанные левой ногой.
__>просто большинство обычных людей это касается только когда в таком стиле пишут OpenSSL и потом удивлются, что там глк на глюке. а так то такой это только проблема товарищей из opencv как они этот код будут расширять, отлаживать или портировать. да и если весь opencv таквоц то судя по всему opencv работает только из-за компенсации багов друг другом и только ра малине девелоперов и только на их примерах

А по мне так OpenCV прекрасно работает, и даже с CUDA нет никаких проблем. Особенность OpenCV в малой связности, а это значит изменение одного не влечёт багов другого. Вот разобъёте вы проект на несколько функций, но они используются ровно один раз, дальше что? Замечу речь не идет об объектно-ориентированных приложениях, вот эти самые функции могут выступать в них всего лишь кирпичиками. В линуксе, когда работаешь с оборудованием всякие лишние деления заканчиваются не просто плохо, а ужасно. Назовите историю успеха мне интересно будет послушать.

Так то я на Qt в последние 7 лет подсел, так что не стал бы обхаивать за зря предложенную идеологию всяких энтерпрайзов, а даже напротив. Но увы, почему-то то, что прекрасно пашет в одних решениях, в других терпит полное фиаско. Впрочем Qt тоже не особо всё делит, можно поделить гораздо больше. Хорошо делят и абстрагируют в Java, но она тормоз, причём может быть именно поэтому и тормоз. Излишнее деление не всегда проявляется сразу, пока оно не дойдёт до маниакального состояния.

Иными словами в прошлом я бы тоже всё поделил на такой задаче, и поделил, но наступил облом. Практика Qt, а до этого .NET и так далее не помогли, а лишь мешали. Хотя, когда лепишь точно так же какое-нибудь гуишное приложение, всё работает на ура. И использование return срабатывает просто отлично. В общем мой вывод, что сишники тоже кое в чём правы. Вот тогда мир разделился ещё на две части, один это динамическая архитектура, второй молотилка битов. Она может быть как процедурной, так и в обобщённой парадигме. И молотилки имеют свою специфику, их нельзя судить с позиции ООП.
Re[5]: профи или упоротый
От: __kot2  
Дата: 20.02.15 03:22
Оценка: +1 -1
Здравствуйте, velkin, Вы писали:
V>А по мне так OpenCV прекрасно работает, и даже с CUDA нет никаких проблем.
я не в курсе как он работет, если честно.
у со своей колокольни кому сказать что куча научного софта на самом деле гавно, которое прдюсит невалидный кал огромных обьемов, загрязнящий что то осмысленное. кал этот совершенно бесполезно испавлять. только его аффтар понимает в этих макаронах хоть что-то. это называется job security, да, когда только тпкущие разработчики могут что-то там сделать, а остальные потеряются где-то пытаясь понять что имелось в виду во всей вот этой вот бадяге.
Re[2]: Re: профи или упоротый
От: Serg27  
Дата: 20.02.15 03:54
Оценка:
Прекрасный анализ этого куска кода.
Я, честно говоря, дошел в коде только до места с бинаризацией изображения (где магическое число "160"), дальше не стал смотреть. Проблема с goto тут самая последняя. В общем-то как код на один раз сойдет (как уже писали), но меня смущает прекрасное оформление этого кода. То ли корпоративные стандарты оформления свято блюдутся даже для одно-минутных поделок, то ли код был написан в исследовательских целях на matlabe (например) каким-то экспертом, а затем был перенесен на C++ уже другим человеком, которому дали это свыше как "божественное откровение". Склоняюсь ко второму варианту, так как наблюдал такое не однократно.
Re[3]: профи или упоротый
От: pestis  
Дата: 20.02.15 06:45
Оценка: -5
Здравствуйте, velkin, Вы писали:


V>Ну или разработчики OpenCV как вариант.


Это низкоуровневая обработка изображений. Ее вообще нужно писать на чистом С хорошим оптимизирующим компилятором. Просто разработчики OpenCV в основной массе школьники, копипастящие алгоритмы из учебников.
Re[4]: профи или упоротый
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 20.02.15 07:52
Оценка:
Здравствуйте, pestis, Вы писали:

P>Это низкоуровневая обработка изображений. Ее вообще нужно писать на чистом С хорошим оптимизирующим компилятором. Просто разработчики OpenCV в основной массе школьники, копипастящие алгоритмы из учебников.

Ничего не надо писать на С. Везде можно использовать С++ и по производительности он будет как С-шный код если ты умеешь писать на С++.
Sic luceat lux!
Re[5]: профи или упоротый
От: Molchalnik  
Дата: 20.02.15 08:23
Оценка:
Здравствуйте, jyuyjiyuijyu, Вы писали:

J>можно и функцию но тогда будет множество мелких функций, тут как я вижу одна функция не требующая её дробить еще на несколько функций


Видать, ты старой школы, сейчас причины для дробления функции — читаемость и логический уровень. инлайн решает проблемы скорости.
Re[5]: профи или упоротый
От: Evgeny.Panasyuk Россия  
Дата: 20.02.15 09:07
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Везде можно использовать С++ и по производительности он будет как С-шный код если ты умеешь писать на С++.


Вообще-то нормальный C++ код будет быстрее, за счёт бесплатных абстракций.
Adobe/Boost — Generic Image Library
Re[3]: профи или упоротый
От: Кодт Россия  
Дата: 20.02.15 09:56
Оценка:
Здравствуйте, velkin, Вы писали:

V>Ну или разработчики OpenCV как вариант.


Такое впечатление, что разработчики OpenCV просто перепёрли сишный код на плюсы — да и то, лишь ради самоочистки пяти локальных массивов.
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.