void ConvertColor_BGR2GRAY_BT709_simd(const cv::Mat& src, cv::Mat& dst) { CV_Assert(CV_8UC3 == src.type()); cv::Size sz = src.size(); dst.create(sz, CV_8UC1); #ifdef HAVE_SSE // __m128i ssse3_blue_indices_0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0); // __m128i ssse3_blue_indices_1 = _mm_set_epi8(-1, -1, -1, -1, -1, 14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1); // __m128i ssse3_blue_indices_2 = _mm_set_epi8(13, 10, 7, 4, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); // __m128i ssse3_green_indices_0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1); // __m128i ssse3_green_indices_1 = _mm_set_epi8(-1, -1, -1, -1, -1, 15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1); // __m128i ssse3_green_indices_2 = _mm_set_epi8(14, 11, 8, 5, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); __m128i ssse3_red_indices_0 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 14, 11, 8, 5, 2); __m128i ssse3_red_indices_1 = _mm_set_epi8(-1, -1, -1, -1, -1, -1, 13, 10, 7, 4, 1, -1, -1, -1, -1, -1); __m128i ssse3_red_indices_2 = _mm_set_epi8(15, 12, 9, 6, 3, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); #endif for (int y = 0; y < sz.height; y++) { const uchar *psrc = src.ptr<uchar>(y); uchar *pdst = dst.ptr<uchar>(y); int x = 0; #ifdef HAVE_SSE // Here is 16 times unrolled loop for vector processing for (; x <= sz.width - 16; x += 16) { __m128i chunk0 = _mm_loadu_si128((const __m128i*)(psrc + x*3 + 16*0)); __m128i chunk1 = _mm_loadu_si128((const __m128i*)(psrc + x*3 + 16*1)); __m128i chunk2 = _mm_loadu_si128((const __m128i*)(psrc + x*3 + 16*2)); __m128i red = _mm_or_si128(_mm_or_si128(_mm_shuffle_epi8(chunk0, ssse3_red_indices_0), _mm_shuffle_epi8(chunk1, ssse3_red_indices_1)), _mm_shuffle_epi8(chunk2, ssse3_red_indices_2)); /* ??? */ _mm_storeu_si128((__m128i*)(pdst + x), red); } #endif // Process leftover pixels for (; x < sz.width; x++) { /* ??? */ } } // ! Remove this before writing your optimizations ! ConvertColor_BGR2GRAY_BT709_fpt(src, dst); }
void skeletonize(const cv::Mat &input, cv::Mat &output, bool save_images) { TS(total); TS(imwrite_0); if (save_images) cv::imwrite("0-input.png", input); TE(imwrite_0); // Convert to grayscale my cv::Mat gray_image_my; ConvertColor_BGR2GRAY_BT709_fpt(input, gray_image_my); if (save_images) cv::imwrite("1-convertcolor_my.png", gray_image_my); // Convert to grayscale my cv::Mat gray_image; ConvertColor_BGR2GRAY_BT709(input, gray_image); if (save_images) cv::imwrite("1-convertcolor.png", gray_image); // Downscale input image cv::Mat small_image; cv::Size small_size(input.cols / 1.5, input.rows / 1.5); ImageResize(gray_image, small_image, small_size); if (save_images) cv::imwrite("2-resize.png", small_image); // Binarization and inversion cv::threshold(small_image, small_image, 128, 255, cv::THRESH_BINARY_INV); if (save_images) cv::imwrite("3-threshold.png", small_image); // Thinning cv::Mat thinned_image; GuoHallThinning(small_image, thinned_image); if (save_images) cv::imwrite("4-thinning.png", thinned_image); // Back inversion output = 255 - thinned_image; if (save_images) cv::imwrite("5-output.png", output); TE(total); }