示例#1
0
/*******************************************************************************
* Function:      doubleThresholdByValue  
* Description:   performs double local thresholding using Otsu's method
* Arguments:
	percentage      -   parameter for amount of lowering Otsu threshold
	roiMask         -   ROI binary mask
	
* Returns:       void
* Comments:
* Revision: 
*******************************************************************************/
void
FGExtraction::doubleThresholdByValue(double percentage, Mat roiMask)
{
	int u = 0;
	int thresh = getOtsuThreshold(0, 255, &u, roiMask);
	int highThresh = thresh - int(percentage*(thresh - u));
	int lowThresh = thresh - int(1.4*percentage*(thresh - u));

#ifdef DEBUG
	//cout << "th_H = " << highThresh << "; th_L = " << lowThresh << "; \n";
#endif

	Mat maskedFG;
	bitwise_and(_inImg, roiMask, maskedFG);
	
	// generate high and low look-up tables
	Mat highLUT(1, 256, CV_8U);
	Mat lowLUT(1, 256, CV_8U);
    uchar* highData = highLUT.data; 
	uchar* lowData = lowLUT.data;
    for(int i = 0; i < 256; ++i){
        highData[i] = i <= highThresh ? 0 : 255;
		lowData[i] = i <= lowThresh ? 0 : 255;
	}

	// threshold by using look-up tables
	LUT(maskedFG, highLUT, _highMask);
	LUT(maskedFG, lowLUT, _lowMask);
	bitwise_or(_fgHighImg, _highMask, _fgHighImg, roiMask);
	bitwise_or(_fgLowImg, _lowMask, _fgLowImg, roiMask);
}
示例#2
0
StartleServer::StartleServer(unsigned short sock_address,wxStatusBar *status_bar,wxTextCtrl *text_ctrl,StartleFrame *startle_frame)
:GSIServer(sock_address,status_bar,text_ctrl,startle_frame) //send -1 as GSISockServer so that ctor doesn't construct it
{
//init data for the Amplitude LUT, 127 possible values, 1-125 dB and max output (127)
//0=MUTE (104dB output diconnected from input in LM1972)

    int dbLUT[STLMaxDB+1]={
		      127,												 //100dB
				  126, 125, 124, 123, 122, 121, 120, 119, 118,   //70-78dB attenuation LM1972 .5dB steps low-> high volume
              117, 116, 115, 114, 113, 112, 111, 110, 109, 108,   //60-69dB attenuation
              107, 106, 105, 104, 103, 102, 101, 100, 99,  98,	  //50-59dB attenuation
              97,  96,											  //48-49dB attenuation
						95,  94,  93,  92,  91,  90,  89,  88,	  //44-47.5dB
              87,  86,  85,  84,  83,  82,  81,  80,  79,  78,	  //39-43.5dB attenuation
              77,  76,  75,	 74,  73,  72,  71,  70,  69,  68,	  //34-38.5dB attenuation										  //50-48dB attenuation
			  67,  66,  65,  64,  63,  62,  61,  60,  59,  58,	  //29-33.5dB attenuation
			  57,  56,  55,  54,  53,  52,  51,  50,  49,  48,	  //24-28.5dB attenuation
			  47,  46,  45,  44,  43,  42,  41,  40,  39,  38,	  //19-23.5dB attenuation
			  37,  36,  35,  34,  33,  32,  31,  30,  29,  28,	  //14-18.5dB attenuation
			  27,  26,  25,  24,  23,  22,  21,  20,  19,  18,	  //9-13.5dB attenuation
			  17,  16,  15,  14,  13,  12,  11,  10,  9,   8,	  //4-8.5dB attenuation
			  7,   6,   5,   4,   3,   2,   1,   0 				  //0.0-3.5dB
              };


    m_StartleFrame=startle_frame;
    m_queuedADC=false;           //are we awaiting an ADC? ie will startle box send us data
    m_numADCDataPoints=0;

    m_dBLUT=DEBUG_NEW LUT(STLMaxLUTIndex+1,STLMaxAmplitudeDB,dbLUT);
    m_dBNoiseLUT=DEBUG_NEW LUT(STLMaxLUTIndex+1,STLMaxNoiseAmplitudeDB,dbLUT);
}
示例#3
0
/*******************************************************************************
* Function:      histBackProject  
* Description:   performs histogram backprojection
* Arguments:
	hist          -   histogram
	histSize      -   number of bins in histogram
	roiMask       -   ROI mask
	
* Returns:       Mat - the histogram backproject image
* Comments:
* Revision: 
*******************************************************************************/
Mat
FGExtraction::histBackProject(InputArray hist, Mat roiMask)
{
	Mat histMat = hist.getMat();
	int binWidth = histMat.rows;

	// generate high and low look-up tables
	Mat lookUpTable(1, 256, CV_32F);
    for(int i = 0; i < 256; ++i)
        lookUpTable.at<float>(0, i) = histMat.at<float>(i/binWidth, 0);

	//cout << lookUpTable << endl;
	//system("Pause");

	// perform histogram backprojection via the look-up table
	Mat backProj = Mat(_inImg.size(), CV_32F);
	LUT(_inImg, lookUpTable, backProj);
	
	/*
    for (int y = 0; y < _inImg.rows; ++y){
        for (int x = 0; x < _inImg.cols; ++x){
			if(roiMask.at<uchar>(y, x) > 0){
				int idx = _inImg.at<uchar>(y, x) / binWidth;
                float bp = histMat.at<float>(idx, 0);
                backProj.at<float>(y, x) = bp;
			}
		}
	}
	*/

	return backProj;
}
std::tuple<cv::Mat, cv::Mat, signed int, signed int> FreeTypeTextPrinter::GetCharMat() const
{
	// bitmap_left为左距  bitmap_top为图形顶部到基线的距离基线
	auto &bitmap = ft_face_->glyph->bitmap;

	// 就地构造 免除手动内存拷贝  注意,生成下一个字符时内存会被清除
	cv::Mat char_bitmap(cv::Size(bitmap.width, bitmap.rows), CV_8U, bitmap.buffer);
	cv::Mat char_img;
	// 处理非打印字符问题
	if (0 != char_bitmap.rows || 0 != char_bitmap.cols)
	{
		char_img = char_bitmap.clone();
	}
	else
	{
		char_img = cv::Mat(cv::Size(std::max(bitmap.width, empty_width_), std::max(bitmap.rows, empty_width_)), CV_8U, cv::Scalar(0));
	}

	cvtColor(char_img, char_img, CV_GRAY2BGR);

	cv::Mat mask;	// 填涂掩码  用来挖除目标图像的掩码区域以便去除字体色彩不饱和导致字体模糊的副作用
	bitwise_not(char_img, mask);

	LUT(char_img, color_lut_, char_img);

	return std::make_tuple(char_img, mask, ft_face_->glyph->bitmap_top, ft_face_->glyph->bitmap_left);
}
示例#5
0
Mat apply(Image& img,int type){
	int dim(256);
	Mat lut(1, &dim, CV_8UC(img.dst.channels()));
	switch (type)
	{
	case 0:
	if (img.dst.channels()==1)
	{
		for (int i = 0; i < 256; i++)
			lut.at<uchar>(i) = uchar(255*log2(i+1)/8);
	}
	else
	{
		for (int i = 0; i < 256; i++)
		{
			lut.at<Vec3b>(i)[0] = uchar(255 * log2(i + 1) / 8);
			lut.at<Vec3b>(i)[1] = uchar(255 * log2(i + 1) / 8);
			lut.at<Vec3b>(i)[2] = uchar(255 * log2(i + 1) / 8);
		}
	}
		break;
	case 1:
	if (img.dst.channels()==1)
	{
		for (int i = 0; i < 256; i++)
			lut.at<uchar>(i) = uchar(16 * sqrt(i + 1));
	}
	else
	{
		for (int i = 0; i < 256; i++)
		{
			lut.at<Vec3b>(i)[0] = uchar(16*sqrt(i+1));
			lut.at<Vec3b>(i)[1] = uchar(16*sqrt(i+1));
			lut.at<Vec3b>(i)[2] = uchar(16*sqrt(i+1));
		}
	}
		break;
	case 2:
	if (img.dst.channels()==1)
	{
		for (int i = 0; i < 256; i++)
			lut.at<uchar>(i) = uchar(84*pow(i,0.2));
	}
	else
	{
		for (int i = 0; i < 256; i++)
		{
			lut.at<Vec3b>(i)[0] = uchar(48*pow(i,0.3));
			lut.at<Vec3b>(i)[1] = uchar(48*pow(i,0.3));
			lut.at<Vec3b>(i)[2] = uchar(48*pow(i,0.3));
		}
	}
		break;
	default:
		break;
	}
	LUT(img.original, lut, img.dst);
	return img.dst;
}
示例#6
0
/* Image gamma correction 
 *
 * PARAMETERS:
 * 			- src: Mat to perform gamma correction
 * 
 * RETURN: --
 */
void gammaCorrection(const Mat& src, float factor)
{

	float inverse_gamma = 1.0/2.5;
	Mat lut_matrix(256, 1, CV_8UC1);
	uchar* ptr = lut_matrix.ptr<uchar>(0);
	for( int i = 0; i < 256; ++i)
		ptr[i] =  saturate_cast<uchar>(pow(i/255.0, inverse_gamma)*255.0);
	LUT(src, lut_matrix, src);
}
cv::Mat ENetSegmenter::Visualization(cv::Mat in_prediction_map, std::string in_lookuptable_file)
{

	cv::cvtColor(in_prediction_map.clone(), in_prediction_map, CV_GRAY2BGR);
	cv::Mat label_colours = cv::imread(in_lookuptable_file, 1);
	cv::cvtColor(label_colours, label_colours, CV_RGB2BGR);
	cv::Mat output_image;
	LUT(in_prediction_map, label_colours, output_image);

	return output_image;
}
示例#8
0
    void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response)
    {
        std::vector<Mat> images;
        src.getMatVector(images);
        Mat times = _times.getMat();

        CV_Assert(images.size() == times.total());
        checkImageDimensions(images);
        CV_Assert(images[0].depth() == CV_8U);

        int channels = images[0].channels();
        int CV_32FCC = CV_MAKETYPE(CV_32F, channels);

        dst.create(images[0].size(), CV_32FCC);
        Mat result = dst.getMat();

        Mat response = input_response.getMat();
        if(response.empty()) {
            float middle = LDR_SIZE / 2.0f;
            response = linearResponse(channels) / middle;
        }
        CV_Assert(response.rows == LDR_SIZE && response.cols == 1 &&
                  response.channels() == channels);

        result = Mat::zeros(images[0].size(), CV_32FCC);
        Mat wsum = Mat::zeros(images[0].size(), CV_32FCC);
        for(size_t i = 0; i < images.size(); i++) {
            Mat im, w;
            LUT(images[i], weight, w);
            LUT(images[i], response, im);

            result += times.at<float>((int)i) * w.mul(im);
            wsum += times.at<float>((int)i) * times.at<float>((int)i) * w;
        }
        result = result.mul(1 / wsum);
    }
示例#9
0
 void ColorMap::operator()(InputArray _src, OutputArray _dst) const
 {
     if(_lut.total() != 256)
         CV_Error(Error::StsAssert, "cv::LUT only supports tables of size 256.");
     Mat src = _src.getMat();
     // Return original matrix if wrong type is given (is fail loud better here?)
     if(src.type() != CV_8UC1 && src.type() != CV_8UC3)
     {
         src.copyTo(_dst);
         return;
     }
     // Turn into a BGR matrix into its grayscale representation.
     if(src.type() == CV_8UC3)
         cvtColor(src.clone(), src, COLOR_BGR2GRAY);
     cvtColor(src.clone(), src, COLOR_GRAY2BGR);
     // Apply the ColorMap.
     LUT(src, _lut, _dst);
 }
示例#10
0
void quantize1(Mat& src, Mat& dst) 
{
    //uchar steps[4] = {50, 100, 150, 255};
    uchar steps[4];
    float step_prob[] = { 0.1f, 0.2f, 0.2f, 0.5f};
    getQuantizeSteps(src, step_prob, 4, steps);

    uchar step_val[4] = {10, 50, 100, 255};
    //uchar step_val[4] = {200, 210, 220, 255};

    uchar buffer[256];
    int j=0;
    for(int i=0; i!=256; ++i) {
        if(i > steps[j])
            j++;
        buffer[i] = step_val[j];
    } 
    Mat table(1, 256, CV_8U, buffer, sizeof(buffer));
    LUT(src, table, dst);
}
static void colorExtraction(const cv::Mat& src, // input HSV image
                            cv::Mat*       dst, // specified color extracted binarized image
                            const double   hue_lower, const double hue_upper, // hue thresholds
                            const double   sat_lower, const double sat_upper, // satulation thresholds
                            const double   val_lower, const double val_upper) // value thresholds
{
  /* create imput image copy */
  cv::Mat input_img = src.clone();

  *dst = cv::Scalar::all(0);

  /*
    ref:
    http://qiita.com/crakaC/items/65fab9d0b0ac29e68ab6
   */

  /* create LookUp Table */
  cv::Mat lut(256, 1, CV_8UC3);
  for (int i=0; i<256; i++)
    {
	  lut.at<cv::Vec3b>(i)[0] = (IsRange(hue_lower, hue_upper, Actual_Hue(i))) ? 255 : 0;
	  lut.at<cv::Vec3b>(i)[1] = (IsRange(sat_lower, sat_upper, Actual_Sat(i))) ? 255 : 0;
	  lut.at<cv::Vec3b>(i)[2] = (IsRange(val_lower, val_upper, Actual_Val(i))) ? 255 : 0;
    }

  /* apply LUT to input image */
  cv::Mat extracted(input_img.rows, input_img.cols, CV_8UC3);
  LUT(input_img, lut, extracted);

  /* divide image into each channel */
  std::vector<cv::Mat> channels;
  split(extracted, channels);

  /* create mask */
  bitwise_and(channels[0], channels[1], *dst);
  bitwise_and(*dst, channels[2], *dst);


} /* static void colorExtraction() */
BYTE CHistogram::LUT(BYTE *pValue, UINT DataType)
{
	switch(DataType)
	{
	case Pixel_Byte:
		return LUT(*(BYTE*)pValue);;
	case Pixel_Int16:
		return LUT(*(unsigned short*)pValue);
	case Pixel_SInt16:
		return LUT(*(short*)pValue);
	case Pixel_Int32:
		return LUT(*(unsigned int*)pValue);
	case Pixel_SInt32:
		return LUT(*(int*)pValue);
	case Pixel_Float:
		return LUT(*(float*)pValue);
	case Pixel_Double:
		return LUT(*(double*)pValue);
	default:
		return 0;
	}
	return 0;
}
示例#13
0
    void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response)
    {
        std::vector<Mat> images;
        src.getMatVector(images);
        Mat times = _times.getMat();

        CV_Assert(images.size() == times.total());
        checkImageDimensions(images);
        CV_Assert(images[0].depth() == CV_8U);

        int channels = images[0].channels();
        Size size = images[0].size();
        int CV_32FCC = CV_MAKETYPE(CV_32F, channels);

        dst.create(images[0].size(), CV_32FCC);
        Mat result = dst.getMat();

        Mat response = input_response.getMat();

        if(response.empty()) {
            response = linearResponse(channels);
            response.at<Vec3f>(0) = response.at<Vec3f>(1);
        }

        Mat log_response;
        log(response, log_response);
        CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 &&
                  log_response.channels() == channels);

        Mat exp_values(times);
        log(exp_values, exp_values);

        result = Mat::zeros(size, CV_32FCC);
        std::vector<Mat> result_split;
        split(result, result_split);
        Mat weight_sum = Mat::zeros(size, CV_32F);

        for(size_t i = 0; i < images.size(); i++) {
            std::vector<Mat> splitted;
            split(images[i], splitted);

            Mat w = Mat::zeros(size, CV_32F);
            for(int c = 0; c < channels; c++) {
                LUT(splitted[c], weights, splitted[c]);
                w += splitted[c];
            }
            w /= channels;

            Mat response_img;
            LUT(images[i], log_response, response_img);
            split(response_img, splitted);
            for(int c = 0; c < channels; c++) {
                result_split[c] += w.mul(splitted[c] - exp_values.at<float>((int)i));
            }
            weight_sum += w;
        }
        weight_sum = 1.0f / weight_sum;
        for(int c = 0; c < channels; c++) {
            result_split[c] = result_split[c].mul(weight_sum);
        }
        merge(result_split, result);
        exp(result, result);
    }
示例#14
0
文件: Sample.cpp 项目: duo3d/samples
int main(int argc, char* argv[])
{
	// Build color lookup table for depth display
	Mat colorLut = Mat(cv::Size(256, 1), CV_8UC3);
	for(int i = 0; i < 256; i++)
		colorLut.at<Vec3b>(i) = (i==0) ? Vec3b(0, 0, 0) : HSV2RGB(i/256.0f, 1, 1);

	// Open Dense3D
	Dense3DMTInstance dense3d;
	if(!Dense3DOpen(&dense3d))
	{
		printf("Could not open Dense3DMT library\n");
		return 1;
	}

	DUOInstance duo = GetDUOInstance(dense3d);

	char tmp[260];
	GetDUODeviceName(duo,tmp);
	printf("DUO Device Name:      '%s'\n", tmp);
	GetDUOSerialNumber(duo, tmp);
	printf("DUO Serial Number:    %s\n", tmp);
	GetDUOFirmwareVersion(duo, tmp);
	printf("DUO Firmware Version: v%s\n", tmp);
	GetDUOFirmwareBuild(duo, tmp);
	printf("DUO Firmware Build:   %s\n", tmp);
	printf("DUOLib Version:       v%s\n", GetDUOLibVersion());
	printf("Dense3DMT Version:    v%s\n", Dense3DGetLibVersion());

	// Set the Dense3D license (visit https://duo3d.com/account)
	if(!SetDense3DLicense(dense3d, "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX")) // <-- Put your Dense3D license
	{
		printf("Invalid or missing Dense3D license. To get your license visit https://duo3d.com/account\n");
		// Close Dense3D library
		Dense3DClose(dense3d);
		return 1;
	}
	// Set the image size
	if(!SetDense3DImageInfo(dense3d, WIDTH, HEIGHT, FPS))
	{
		printf("Invalid image size\n");
		// Close Dense3D library
		Dense3DClose(dense3d);
		return 1;
	}

	// Set Dense3D parameters
	Dense3DParams params;
	params.scale = 0;
    params.mode = 0;
    params.numDisparities = 2;
    params.sadWindowSize = 6;
    params.preFilterCap = 28;
    params.uniqenessRatio = 27;
    params.speckleWindowSize = 52;
    params.speckleRange = 14;
	if(!SetDense3Params(dense3d, params))
    {
        printf("GetDense3Params error\n");
		// Close Dense3D library
		Dense3DClose(dense3d);
        return 1;
    }

	// Queue used to receive Dense3D frames
	Dense3DFrameQueue d3dq;

	// Start DUO capture and Dense3D processing
	if(!Dense3DStart(dense3d, [](const PDense3DFrame pFrameData, void *pUserData)
					{
                        D3DFrame frame;
                        Size frameSize(pFrameData->duoFrame->width, pFrameData->duoFrame->height);
                        frame.leftImg = Mat(frameSize, CV_8U, pFrameData->duoFrame->leftData);
                        frame.rightImg = Mat(frameSize, CV_8U, pFrameData->duoFrame->rightData);
                        frame.disparity = Mat(frameSize, CV_32F, pFrameData->disparityData);
                        frame.depth = Mat(frameSize, CV_32FC3, pFrameData->depthData);
                        ((Dense3DFrameQueue*)pUserData)->push(frame);
					}, &d3dq))
	{
		printf("Dense3DStart error\n");
		// Close Dense3D library
		Dense3DClose(dense3d);
		return 1;
	}

	// Set exposure, LED brightness and camera orientation
	SetDUOExposure(duo, 85);
	SetDUOLedPWM(duo, 28);
	SetDUOVFlip(duo, true);

	// Run capture loop until <Esc> key is pressed
	while((cvWaitKey(1) & 0xff) != 27)
	{
		D3DFrame d3DFrame;
		if(!d3dq.pop(d3DFrame))
			continue;

		Mat disp8;
		d3DFrame.disparity.convertTo(disp8, CV_8UC1, 255.0/(params.numDisparities*16));
		Mat rgbBDisparity;
		cvtColor(disp8, rgbBDisparity, COLOR_GRAY2BGR);
		LUT(rgbBDisparity, colorLut, rgbBDisparity);

		// Display images
		imshow("Left Image", d3DFrame.leftImg);
		imshow("Right Image", d3DFrame.rightImg);
		imshow("Disparity Image", rgbBDisparity);
	}
	destroyAllWindows();

	Dense3DStop(dense3d);
	Dense3DClose(dense3d);
	return 0;
}
void TrafficLightDetector::brightnessDetect(const cv::Mat &input) {

  cv::Mat tmpImage;
  input.copyTo(tmpImage);

  /* contrast correction */
  cv::Mat tmp;
  cvtColor(tmpImage, tmp, CV_BGR2HSV);
  std::vector<cv::Mat> hsv_channel;
  split(tmp, hsv_channel);

  float correction_factor = 10.0;
  uchar lut[256];
  for (int i=0; i<256; i++) {
    lut[i] = 255.0 / (1 + exp(-correction_factor*(i-128)/255));
  }

  LUT(hsv_channel[2], cv::Mat(cv::Size(256, 1), CV_8U, lut), hsv_channel[2]);
  merge(hsv_channel, tmp);
  cvtColor(tmp, tmpImage, CV_HSV2BGR);

  for (int i = 0; i < static_cast<int>(contexts.size()); i++) {
    Context context = contexts.at(i);

    if (context.topLeft.x > context.botRight.x)
      continue;

    /* extract region of interest from input image */
    cv::Mat roi = tmpImage(cv::Rect(context.topLeft, context.botRight));

    /* convert color space (BGR -> HSV) */
    cv::Mat roi_HSV;
    cvtColor(roi, roi_HSV, CV_BGR2HSV);

    /* search the place where traffic signals seem to be */
    cv::Mat    signalMask    = signalDetect_inROI(roi_HSV, input.clone(), context.lampRadius, context.topLeft);

    /* detect which color is dominant */
    cv::Mat extracted_HSV;
    roi.copyTo(extracted_HSV, signalMask);

    // extracted_HSV.copyTo(roi);
    // imshow("tmpImage", tmpImage);
    // waitKey(5);

    cvtColor(extracted_HSV, extracted_HSV, CV_BGR2HSV);

    int red_pixNum    = 0;
    int yellow_pixNum = 0;
    int green_pixNum  = 0;
    int valid_pixNum  = 0;
    for (int y=0; y<extracted_HSV.rows; y++)
      {
        for (int x=0; x<extracted_HSV.cols; x++)
          {
            /* extract H, V value from pixel */
            double hue = Actual_Hue(extracted_HSV.at<cv::Vec3b>(y, x)[0]);
            uchar  val = extracted_HSV.at<cv::Vec3b>(y, x)[2];

            if (val == 0) {
              continue;         // this is masked pixel
            }
            valid_pixNum++;

            /* search which color is actually bright */
            if (IsRange(thSet.Red.Hue.lower, thSet.Red.Hue.upper, hue)) {
              red_pixNum++;
            }

            if (IsRange(thSet.Yellow.Hue.lower, thSet.Yellow.Hue.upper, hue)) {
              yellow_pixNum++;
            }

            if (IsRange(thSet.Green.Hue.lower, thSet.Green.Hue.upper, hue)) {
              green_pixNum++;
            }
          }
    }

    // std::cout << "(green, yellow, red) / valid = (" << green_pixNum << ", " << yellow_pixNum << ", " << red_pixNum << ") / " << valid_pixNum <<std::endl;

    bool isRed_bright;
    bool isYellow_bright;
    bool isGreen_bright;

    if (valid_pixNum > 0) {
      isRed_bright    = ( ((double)red_pixNum / valid_pixNum)    > 0.45) ? true : false; // detect red a little largely
      isYellow_bright = ( ((double)yellow_pixNum / valid_pixNum) > 0.5) ? true : false;
      isGreen_bright  = ( ((double)green_pixNum / valid_pixNum)  > 0.5) ? true : false;
    } else {
      isRed_bright    = false;
      isYellow_bright = false;
      isGreen_bright  = false;
    }

    int currentLightsCode = getCurrentLightsCode(isRed_bright, isYellow_bright, isGreen_bright);
    contexts.at(i).lightState = determineState(contexts.at(i).lightState, currentLightsCode, &(contexts.at(i).stateJudgeCount));

    roi.setTo(cv::Scalar(0));
  }
}