精华内容
下载资源
问答
  • 利用ffmpeg实现桌面采集功能,采集桌面后进行解码,图像转换为YUV420P格式,在经过h264编码,最后通过网络TCP协议进行发送。代码可以编译,在没有网络接收服务器的情况下,可将编码后的packet保存成本地的.h264文件
  • ffmpeg视频采集功能非常强大,不仅可以采集视频采集卡或USB摄像头的图像,还可以进行屏幕录制,同时还支持以RTP方式将视频流传送给支持RTSP的流媒体服务器,支持直播应用。 ffmpeg在Linux下的视频采集 在Linux...

    ffmpeg视频采集功能非常强大,不仅可以采集视频采集卡或USB摄像头的图像,还可以进行屏幕录制,同时还支持以RTP方式将视频流传送给支持RTSP的流媒体服务器,支持直播应用。

    • ffmpeg在Linux下的视频采集

    在Linux平台上,ffmpeg对V4L2的视频设备提高了很好的支持,如:

    ./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 8 -i /dev/video0 -vcodec h263 -f rtp rtp://192.168.1.105:5060 > /tmp/ffmpeg.sdp

    以上命令表示:采集10秒钟视频,对video4linux2视频设备进行采集,采集QCIF(176*144)的视频,每秒8帧,视频设备为/dev/video0,视频编码为h263,输出格式为RTP,后面定义了IP地址及端口,将该码流所对应的SDP文件重定向到/tmp/ffmpeg.sdp中,将此SDP文件上传到流媒体服务器就可以实现直播了。

    ./ffmpeg -t 10 -f video4linux2 -s 176*144 -r 10 -vpre libx264-hq.ffpreset -i /dev/video0 -vcodec libx264 -f rtp rtp://192.168.1.105:6060 > /tmp/x264.sdp

    这条命令与上面的类似,但是视频编码为h264,由于ffmpeg是用外部库x264支持h264编码,因此h264的视频采集需要更多参数。主要是需要指定-vpre libx264-hq.ffpreset 才可以。

    • ffmpeg在windows下的视频采集

    在windows下关于ffmpeg视频采集的资料非常少,但是ffmpeg还是支持windows下视频采集的。ffmpeg支持windows下video for windows(VFW)设备的视频采集,不过VFW设备已经过时,正在被WDM的视频设备所取代,但是ffmpeg还没有支持WDM的计划,不过好像有将WDM转为VFW的工具,因此ffmpeg还是可以在windows下进行视频采集的。具体命令如下:

    ./ffmpeg -t 10 -f vfwcap -i 0 -r 8 -f mp4 cap.mp4

    具体说明如下:我们采集10秒,采集设备为vfwcap类型设备,第0个vfwcap采集设备(如果系统有多个vfw的视频采集设备,可以通过-i num来选择),每秒8帧,输出方式为文件,格式为mp4。

    展开全文
  • Windows 图像采集(WIA)为Windows 系统提供数字图像获取服务,是图像获取设备获取图像的重要方法之一。WIA提供了MiniDriver和MicroDriver两种方式以支持扫描仪获取图像。本文首先介绍了WIA的一般概念和体系结构,...
  • 大家在做Windows平台RTMP推送或轻量级RTSP服务的时候,不管是采集屏幕还是采集摄像头,亦或屏幕摄像头的叠加模式,总会有这样的诉求,采集到的数据,希望能本地看看具体采集的数据或者图像实际效果,也就是本次介绍...

    背景

    大家在做Windows平台RTMP推送或轻量级RTSP服务的时候,不管是采集屏幕还是采集摄像头,亦或屏幕摄像头的叠加模式,总会有这样的诉求,采集到的数据,希望能本地看看具体采集的数据或者图像实际效果,也就是本次介绍的“预览”功能。

    废话不多说,想上图:

    如何实现

    开始预览

    开始预览,大概的流程是,调用OpenPublisherHandle(),进行初始的数据源类型设置,然后调用Open()接口,获取推送handler,并设置event回调。

    bool CSmartPublisherDemoDlg::OpenPublisherHandle()
    {
    	if ( publisher_handle_ != NULL )
    	{
    		return true;
    	}
    
    	// 视频
    	auto video_option = NT_PB_E_VIDEO_OPTION_NO_VIDEO;
    
    	if ( BST_CHECKED == btn_check_desktop_camera_switch_.GetCheck()
    		|| BST_CHECKED == btn_check_camera_overlay_to_desktop_.GetCheck() 
    		|| BST_CHECKED == btn_check_desktop_overlay_to_camera_.GetCheck() )
    	{
    		// 使用叠加模式
    		video_option = NT_PB_E_VIDEO_OPTION_LAYER;
    	}
    	else if (BST_CHECKED == btn_check_desktop_input_.GetCheck() && BST_CHECKED == btn_check_scale_desktop_.GetCheck())
    	{
    		// 使用叠加模式来实现缩放
    		video_option = NT_PB_E_VIDEO_OPTION_LAYER;
    	}
    	else if (BST_CHECKED == btn_check_desktop_input_.GetCheck() && BST_CHECKED != btn_check_scale_desktop_.GetCheck() )
    	{
    		video_option = NT_PB_E_VIDEO_OPTION_SCREEN;
    	}
    	else if (BST_CHECKED == btn_check_window_input_.GetCheck())
    	{
    		video_option = NT_PB_E_VIDEO_OPTION_WINDOW;
    
    		// video_option = NT_PB_E_VIDEO_OPTION_LAYER;
    	}
    	else if (BST_CHECKED == btn_check_camera_input_.GetCheck())
    	{
    		video_option = NT_PB_E_VIDEO_OPTION_CAMERA;
    	}
    
    	// 音频
    	auto audio_option = NT_PB_E_AUDIO_OPTION_NO_AUDIO;
    
    	audio_option = NT_PB_E_AUDIO_OPTION_NO_AUDIO;
    
    	if ( BST_CHECKED == btn_check_auido_mic_input_.GetCheck()
    		&& BST_CHECKED == btn_check_auido_speaker_input_.GetCheck() )
    	{
    		audio_option = NT_PB_E_AUDIO_OPTION_CAPTURE_MIC_SPEAKER_MIXER;
    	}
    	else if ( BST_CHECKED == btn_check_auido_mic_input_.GetCheck() )
    	{
    		audio_option = NT_PB_E_AUDIO_OPTION_CAPTURE_MIC;
    	}
    	else if (BST_CHECKED == btn_check_auido_speaker_input_.GetCheck())
    	{
    		audio_option = NT_PB_E_AUDIO_OPTION_CAPTURE_SPEAKER;
    	}
    
    	publisher_handle_count_ = 0;
    
    	if ( NT_ERC_OK != publisher_api_.Open(&publisher_handle_,
    		video_option, audio_option, 0, NULL))
    	{
    		AfxMessageBox(_T("Call open failed!"));
    		return false;
    	}
    
    	if ( publisher_handle_ != NULL )
    	{
    		// 设置事件回调
    		publisher_api_.SetEventCallBack(publisher_handle_, GetSafeHwnd(), &NT_PB_SDKPublisherEventHandle);
    
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }

    目前我们的SDK支持以下几种视频源类型,实时预览仅限于编码前数据类型:

    /*定义Video源选项*/
    typedef enum _NT_PB_E_VIDEO_OPTION
    {
    	NT_PB_E_VIDEO_OPTION_NO_VIDEO = 0x0,
    	NT_PB_E_VIDEO_OPTION_SCREEN   = 0x1, // 采集屏幕
    	NT_PB_E_VIDEO_OPTION_CAMERA	  = 0x2, // 摄像头采集
    	NT_PB_E_VIDEO_OPTION_LAYER    = 0x3, // 视频合并,比如桌面叠加摄像头等
    	NT_PB_E_VIDEO_OPTION_ENCODED_DATA = 0x4, // 已经编码的视频数据,目前支持H264
    	NT_PB_E_VIDEO_OPTION_WINDOW   = 0x5, // 采集窗口
    } NT_PB_E_VIDEO_OPTION;

    接着是调用SetCommonOptionToPublisherSDK(),完成叠加和其他参数设定。

    void CSmartPublisherDemoDlg::SetCommonOptionToPublisherSDK()
    {
    	ASSERT(publisher_handle_ != NULL);
    
    	layer_conf_wrappers_.clear();
    
    	// 视频相关设置
    	if ( BST_CHECKED == btn_check_desktop_camera_switch_.GetCheck()
    		|| BST_CHECKED == btn_check_camera_overlay_to_desktop_.GetCheck()
    		|| BST_CHECKED == btn_check_desktop_overlay_to_camera_.GetCheck()
    		|| BST_CHECKED == btn_check_desktop_input_.GetCheck()
    		|| BST_CHECKED == btn_check_window_input_.GetCheck()
    		|| BST_CHECKED == btn_check_camera_input_.GetCheck() )
    	{
    		if ( BST_CHECKED == btn_check_desktop_camera_switch_.GetCheck() )
    		{
    			auto left = GetIntValueFromEdit(&edit_clip_left_);
    			auto top = GetIntValueFromEdit(&edit_clip_top_);
    			auto w = GetIntValueFromEdit(&edit_clip_width_);
    			auto h = GetIntValueFromEdit(&edit_clip_height_);
    
    			// 有一个是0, 就使用全屏
    			if ( w == 0 || h == 0 )
    			{
    				left = 0;
    				top  = 0;
    				GetScreenSize(w, h);
    			}
    			else
    			{
    				// 保证4字节对齐
    				w = NT_ByteAlign(w, 2);
    				h = NT_ByteAlign(h, 4);
    			}
    
    			auto index = 0;
    
    			// 第0层填充RGBA矩形, 目的是保证帧率, 颜色就填充全黑
    			auto rgba_layer_c0 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, true,
    				0, 0, w, h);
    
    			rgba_layer_c0->conf_.red_	= 0;
    			rgba_layer_c0->conf_.green_ = 0;
    			rgba_layer_c0->conf_.blue_	= 0;
    			rgba_layer_c0->conf_.alpha_ = 255;
    
    			layer_conf_wrappers_.push_back(rgba_layer_c0);
    
    			// 第1层是摄像头
    			if ( CB_ERR != cur_sel_camera_index_ )
    			{
    				auto& camera = cameras_[cur_sel_camera_index_];
    				
    				auto camera_layer_c1 = std::make_shared<nt_pb_sdk::CameraLayerConfigWrapperV2>(index++, false,
    					0, 0, w, h);
    
    				strcpy_s(camera_layer_c1->conf_.device_unique_id_utf8_, camera.id_.c_str());
    
    				camera_layer_c1->conf_.is_flip_horizontal_ = BST_CHECKED == btn_check_flip_horizontal_camera_.GetCheck();
    				camera_layer_c1->conf_.is_flip_vertical_   = BST_CHECKED == btn_check_flip_vertical_camera_.GetCheck();
    
    				// 这种叠加模式下不要旋转,否则变形厉害, 要么就定好一个角度,调整宽高,但不要动态旋转
    				camera_layer_c1->conf_.rotate_degress_ = 0;
    
    				layer_conf_wrappers_.push_back(camera_layer_c1);
    			}
    
    			// 第2层是屏幕
    			auto screen_layer_c2 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapper>(index++, true,
    				0, 0, w, h);
    
    			screen_layer_c2->conf_.reserve_ = nullptr;
    			screen_layer_c2->conf_.clip_region_.x_ = left;
    			screen_layer_c2->conf_.clip_region_.y_ = top;
    			screen_layer_c2->conf_.clip_region_.width_  = w;
    			screen_layer_c2->conf_.clip_region_.height_ = h;
    
    			layer_conf_wrappers_.push_back(screen_layer_c2);
    
    
    			// 第3层填充RGBA矩形, 增加半透明效果
    			auto r = GetIntValueFromEdit(&edit_rgba_rect_layer_red_);
    			r = ClipIntValue(r, 0, 255);
    
    			auto g = GetIntValueFromEdit(&edit_rgba_rect_layer_green_);
    			g = ClipIntValue(g, 0, 255);
    
    			auto b = GetIntValueFromEdit(&edit_rgba_rect_layer_blue_);
    			b = ClipIntValue(b, 0, 255);
    
    			auto a = GetIntValueFromEdit(&edit_rgba_rect_layer_alpha_);
    			a = ClipIntValue(a, 0, 255);
    
    			auto rgba_layer_c3 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, a != 0,
    				0, 0, w, h);
    
    				rgba_layer_c3->conf_.red_	= r;
    				rgba_layer_c3->conf_.green_ = g;
    				rgba_layer_c3->conf_.blue_	= b;
    				rgba_layer_c3->conf_.alpha_ = a;
    
    			layer_conf_wrappers_.push_back(rgba_layer_c3);
    
    			// 如果有图片,增加图片层
    			if ( !image_layer_file_name_utf8_.empty()
    				&& image_layer_width_ > 0 
    				&& image_layer_height_ > 0)
    			{
    				auto image_layer_c4 = std::make_shared<nt_pb_sdk::ImageLayerConfigWrapper>(index++, true,
    					image_layer_left_, image_layer_top_, 
    					image_layer_width_, image_layer_height_ );
    
    				strcpy_s(image_layer_c4->conf_.file_name_utf8_, image_layer_file_name_utf8_.c_str());
    				
    				// 图片层是可以增加背景的,有兴趣的话,可以打开看看效果
    				/*image_layer_c4->conf_.is_setting_background_ = 1;
    
    				image_layer_c4->conf_.bk_red_ = 255;
    				image_layer_c4->conf_.bk_green_ = 255;
    				image_layer_c4->conf_.bk_blue_ = 255;*/
    
    				layer_conf_wrappers_.push_back(image_layer_c4);
    			}
    
    			SetLayersConfig();
    
    			publisher_api_.SetFrameRate(publisher_handle_, GetIntValueFromEdit(&edit_frame_rate_));
    
    		}
    		else if (BST_CHECKED == btn_check_camera_overlay_to_desktop_.GetCheck())
    		{
    			auto left = GetIntValueFromEdit(&edit_clip_left_);
    			auto top  = GetIntValueFromEdit(&edit_clip_top_);
    			auto w = GetIntValueFromEdit(&edit_clip_width_);
    			auto h = GetIntValueFromEdit(&edit_clip_height_);
    
    			// 有一个是0, 就使用全屏
    			if ( w == 0 || h == 0 )
    			{
    				left = 0;
    				top = 0;
    				GetScreenSize(w, h);
    			}
    			else
    			{
    				// 保证4字节对齐
    				w = NT_ByteAlign(w, 2);
    				h = NT_ByteAlign(h, 4);
    			}
    
    			auto index = 0;
    
    			/*auto image_layer_c0 = std::make_shared<nt_pb_sdk::ImageLayerConfigWrapper>(index++, true,
    				0, 0, w, h);
    
    				strcpy_s(image_layer_c0->conf_.file_name_utf8_, "D:\\myxxyy\\testpng\\ggdwdd.png");
    
    				image_layer_c0->conf_.is_setting_background_ = 1;
    
    				image_layer_c0->conf_.bk_red_ = 255;
    				image_layer_c0->conf_.bk_green_ = 255;
    				image_layer_c0->conf_.bk_blue_ = 255;
    
    				layer_conf_wrappers_.push_back(image_layer_c0);*/
    
    
    			// 第0层是屏幕
    			auto screen_layer_c0 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapper>(index++, true,
    				0, 0, w, h);
    
    			screen_layer_c0->conf_.reserve_ = nullptr;
    			screen_layer_c0->conf_.clip_region_.x_ = left;
    			screen_layer_c0->conf_.clip_region_.y_ = top;
    			screen_layer_c0->conf_.clip_region_.width_ = w;
    			screen_layer_c0->conf_.clip_region_.height_ = h;
    
    			layer_conf_wrappers_.push_back(screen_layer_c0);
    
    			// 第1层是摄像头
    			if ( CB_ERR != cur_sel_camera_index_ )
    			{
    				auto& camera = cameras_[cur_sel_camera_index_];
    
    				auto c_l = GetIntValueFromEdit(&edit_camera_overlay_left_);
    				auto c_t = GetIntValueFromEdit(&edit_camera_overlay_top_);
    
    				auto c_w = GetIntValueFromEdit(&edit_camera_overlay_width_);
    				auto c_h = GetIntValueFromEdit(&edit_camera_overlay_height_);
    
    				if ( c_w == 0 )
    				{
    					c_w = w / 2;
    				}
    
    				if ( c_h == 0 )
    				{
    					c_h = h / 2;
    				}
    
    				if ( c_w >0 && c_h > 0 )
    				{
    					auto camera_layer_c1 = std::make_shared<nt_pb_sdk::CameraLayerConfigWrapperV2>(index++, true,
    						c_l, c_t, c_w, c_h);
    
    					strcpy_s(camera_layer_c1->conf_.device_unique_id_utf8_, camera.id_.c_str());
    
    					camera_layer_c1->conf_.is_flip_horizontal_ = BST_CHECKED == btn_check_flip_horizontal_camera_.GetCheck();
    					camera_layer_c1->conf_.is_flip_vertical_ = BST_CHECKED == btn_check_flip_vertical_camera_.GetCheck();
    					camera_layer_c1->conf_.rotate_degress_ = GetCameraRotateDegress();
    
    					layer_conf_wrappers_.push_back(camera_layer_c1);
    				}	
    			}
    			
    			SetLayersConfig();
    
    			publisher_api_.SetFrameRate(publisher_handle_, GetIntValueFromEdit(&edit_frame_rate_));
    		}
    		else if (BST_CHECKED == btn_check_desktop_overlay_to_camera_.GetCheck())
    		{
    			if (CB_ERR != cur_sel_camera_index_
    				&& CB_ERR != cur_sel_camera_resolutions_index_
    				&& CB_ERR != cur_sel_camera_frame_rate_index_)
    			{
    				auto& camera = cameras_[cur_sel_camera_index_];
    				auto& cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
    
    				auto index = 0;
    
    				// 第0层是摄像头
    				auto camera_layer_c0 = std::make_shared<nt_pb_sdk::CameraLayerConfigWrapperV2>(index++, true,
    					0, 0, cap.width_, cap.height_);
    
    				strcpy_s(camera_layer_c0->conf_.device_unique_id_utf8_, camera.id_.c_str());
    
    				camera_layer_c0->conf_.is_flip_horizontal_ = BST_CHECKED == btn_check_flip_horizontal_camera_.GetCheck();
    				camera_layer_c0->conf_.is_flip_vertical_   = BST_CHECKED == btn_check_flip_vertical_camera_.GetCheck();
    
    				// 这种叠加模式下不要旋转,否则变形厉害, 要么就定好一个角度,调整宽高,但不要动态旋转
    				camera_layer_c0->conf_.rotate_degress_ = 0;
    
    				layer_conf_wrappers_.push_back(camera_layer_c0);
    
    				// 第1层是屏幕
    				auto screen_layer_c1 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapper>(index++, true,
    					0, 0, cap.width_ / 2, cap.height_/2);
    
    				screen_layer_c1->conf_.reserve_ = nullptr;
    				screen_layer_c1->conf_.clip_region_.x_ = 0;
    				screen_layer_c1->conf_.clip_region_.y_ = 0;
    				screen_layer_c1->conf_.clip_region_.width_ = cap.width_ / 2;
    				screen_layer_c1->conf_.clip_region_.height_ = cap.height_ / 2;
    
    				layer_conf_wrappers_.push_back(screen_layer_c1);
    
    				SetLayersConfig();
    
    				publisher_api_.SetFrameRate(publisher_handle_, cur_sel_camera_frame_rate_index_ + 1);
    			}
    		}
    		else if (BST_CHECKED == btn_check_desktop_input_.GetCheck() && BST_CHECKED == btn_check_scale_desktop_.GetCheck())
    		{
    			int left = 0, top = 0, w = 0, h = 0, scale_w = 0, scale_h = 0;
    
    			GetScreenScaleConfigInfo(left, top, w, h, scale_w, scale_h);
    
    			auto index = 0;
    
    			// 第0层填充RGBA矩形, 目的是保证帧率, 颜色就填充全黑
    			auto rgba_layer_c0 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, true,
    				0, 0, scale_w, scale_h);
    
    			rgba_layer_c0->conf_.red_ = 0;
    			rgba_layer_c0->conf_.green_ = 0;
    			rgba_layer_c0->conf_.blue_ = 0;
    			rgba_layer_c0->conf_.alpha_ = 255;
    
    			layer_conf_wrappers_.push_back(rgba_layer_c0);
    
    			// 第1层是屏幕
    			auto screen_layer_c1 = std::make_shared<nt_pb_sdk::ScreenLayerConfigWrapperV2>(index++, true,
    				0, 0, scale_w, scale_h);
    
    			screen_layer_c1->conf_.reserve1_ = nullptr;
    			screen_layer_c1->conf_.reserve2_ = 0;
    			screen_layer_c1->conf_.clip_region_.x_ = left;
    			screen_layer_c1->conf_.clip_region_.y_ = top;
    			screen_layer_c1->conf_.clip_region_.width_ = w;
    			screen_layer_c1->conf_.clip_region_.height_ = h;
    
    			screen_layer_c1->conf_.scale_filter_mode_ = 3; // 屏幕缩放考虑到清晰度,这里用3,最高缩放质量
    
    			layer_conf_wrappers_.push_back(screen_layer_c1);
    
    			SetLayersConfig();
    
    			publisher_api_.SetFrameRate(publisher_handle_, GetIntValueFromEdit(&edit_frame_rate_));
    		}
    		else if (BST_CHECKED == btn_check_desktop_input_.GetCheck() && BST_CHECKED != btn_check_scale_desktop_.GetCheck())
    		{
    			publisher_api_.SetScreenClip(publisher_handle_,
    				GetIntValueFromEdit(&edit_clip_left_),
    				GetIntValueFromEdit(&edit_clip_top_),
    				GetIntValueFromEdit(&edit_clip_width_),
    				GetIntValueFromEdit(&edit_clip_height_));
    
    			publisher_api_.SetFrameRate(publisher_handle_, GetIntValueFromEdit(&edit_frame_rate_));
    		}
    		else if ( BST_CHECKED == btn_check_window_input_.GetCheck() )
    		{
    			if ( nullptr != cur_sel_capture_window_ )
    			{
    				publisher_api_.SetCaptureWindow(publisher_handle_, cur_sel_capture_window_);
    
    				publisher_api_.SetFrameRate(publisher_handle_, GetIntValueFromEdit(&edit_frame_rate_));
    
    				// 窗口层测试和演示代码++
    
    				/*auto index = 0;
    
    				auto rgba_layer_c0 = std::make_shared<nt_pb_sdk::RGBARectangleLayerConfigWrapper>(index++, true,
    					0, 0, 1280, 720);
    
    				rgba_layer_c0->conf_.red_ = 0;
    				rgba_layer_c0->conf_.green_ = 255;
    				rgba_layer_c0->conf_.blue_ = 0;
    				rgba_layer_c0->conf_.alpha_ = 255;
    
    				layer_conf_wrappers_.push_back(rgba_layer_c0);
    
    				auto window_layer_c1 = std::make_shared<nt_pb_sdk::WindowLayerConfigWrapper>(index++, true,
    					100, 100, 800, 600);
    
    				window_layer_c1->conf_.window_ = cur_sel_capture_window_;
    
    				layer_conf_wrappers_.push_back(window_layer_c1);
    				
    				SetLayersConfig();
    				*/
    
    				// 窗口层测试和演示代码--
    			}
    		}
    		else if (BST_CHECKED == btn_check_camera_input_.GetCheck())
    		{
    			if (CB_ERR != cur_sel_camera_index_
    				&& CB_ERR != cur_sel_camera_resolutions_index_
    				&& CB_ERR != cur_sel_camera_frame_rate_index_)
    			{
    				auto& camera = cameras_[cur_sel_camera_index_];
    				auto& cap = camera.capabilities_[cur_sel_camera_resolutions_index_];
    
    				publisher_api_.SetVideoCaptureDeviceBaseParameter(publisher_handle_,
    					camera.id_.c_str(), cap.width_, cap.height_);
    
    				publisher_api_.SetFrameRate(publisher_handle_, cur_sel_camera_frame_rate_index_+ 1);
    
    				publisher_api_.FlipVerticalCamera(publisher_handle_,
    					BST_CHECKED == btn_check_flip_vertical_camera_.GetCheck());
    
    				publisher_api_.FlipHorizontalCamera(publisher_handle_, 
    					BST_CHECKED == btn_check_flip_horizontal_camera_.GetCheck());
    
    				auto degress = GetCameraRotateDegress();
    				publisher_api_.RotateCamera(publisher_handle_, degress);
    			}
    		}
    
    		publisher_api_.EnableDXGIScreenCapturer(publisher_handle_, BST_CHECKED == btn_check_dxgi_screen_capturer_.GetCheck());
    
    		publisher_api_.DisableAeroScreenCapturer(publisher_handle_, BST_CHECKED == btn_check_capturer_disable_aero_.GetCheck());
    
    		publisher_api_.EnableScreenCaptureLayeredWindow(publisher_handle_, BST_CHECKED == check_capture_layered_window_.GetCheck()?1:0);
    
    		publisher_api_.SetCaptureWindowWay(publisher_handle_, BST_CHECKED == btn_check_wr_way_capture_window_.GetCheck() ? 2 : 1);
    
    		auto cur_video_codec_id = btn_check_h265_encoder_.GetCheck() != BST_CHECKED? NT_MEDIA_CODEC_ID_H264 : NT_MEDIA_CODEC_ID_H265;
    
    		NT_INT32 cur_sel_encoder_id = 0;
    		NT_INT32 cur_sel_gpu = 0;
    
    		auto is_hw_encoder = btn_check_video_hardware_encoder_.GetCheck() == BST_CHECKED;
    		if (is_hw_encoder)
    		{
    			auto cur_sel_hw = combobox_video_encoders_.GetCurSel();
    			if (cur_sel_hw >=0 )
    			{
    				cur_sel_encoder_id = combobox_video_encoders_.GetItemData(cur_sel_hw);
    				cur_sel_gpu = -1;
    
    				auto cur_sel_hw_dev = combobox_video_hardware_encoder_devices_.GetCurSel();
    				if (cur_sel_hw_dev >= 0)
    				{
    					cur_sel_gpu = combobox_video_hardware_encoder_devices_.GetItemData(cur_sel_hw_dev);
    				}
    			}
    			else
    			{
    				is_hw_encoder = false;
    			}
    		}
    
    		if (!is_hw_encoder)
    		{
    			if (NT_MEDIA_CODEC_ID_H264 == cur_video_codec_id)
    			{
    				cur_sel_encoder_id = btn_check_openh264_encoder_.GetCheck() == BST_CHECKED ? 1 : 0;
    			}
    		}
    
    		publisher_api_.SetVideoEncoder(publisher_handle_, is_hw_encoder? 1 : 0, cur_sel_encoder_id, cur_video_codec_id, cur_sel_gpu);
    
    		if ( BST_CHECKED != btn_check_window_input_.GetCheck() )
    		{
    			publisher_api_.SetVideoBitRate(publisher_handle_, GetIntValueFromEdit(&edit_bit_rate_));
    		}
    		else
    		{
    			// 窗口的分辨率会变, 所以设置一组码率下去
    			auto frame_rate = GetIntValueFromEdit(&edit_frame_rate_);
    			SetBitrateGroup(publisher_handle_, frame_rate);
    		}
    
    		publisher_api_.SetVideoQualityV2(publisher_handle_, GetIntValueFromEdit(&edit_video_quality_));
    
    		publisher_api_.SetVideoMaxBitRate(publisher_handle_, GetIntValueFromEdit(&edit_video_max_bitrate_));
    
    		publisher_api_.SetVideoKeyFrameInterval(publisher_handle_, GetIntValueFromEdit(&edit_key_frame_));
    
    		if (NT_MEDIA_CODEC_ID_H264 == cur_video_codec_id)
    		{
    			auto profile_sel = combox_h264_profile_.GetCurSel();
    			if (profile_sel != CB_ERR)
    			{
    				publisher_api_.SetVideoEncoderProfile(publisher_handle_, profile_sel + 1);
    			}
    		}
    
    		publisher_api_.SetVideoEncoderSpeed(publisher_handle_, GetIntValueFromEdit(&edit_video_encode_speed_));
    
    		// 清除编码器所有的特定的参数
    		publisher_api_.ClearVideoEncoderSpecialOptions(publisher_handle_);
    
    		if (cur_sel_encoder_id == 1)
    		{
    			// qp_max 和 qp_min 当前只对openh264有效, 这里也就只在openh264使用的场景下设置配置值
    			publisher_api_.SetVideoEncoderQPMax(publisher_handle_, GetIntValueFromEdit(&edit_qp_max_));
    			publisher_api_.SetVideoEncoderQPMin(publisher_handle_, GetIntValueFromEdit(&edit_qp_min_));
    
    			// openh264 配置特定参数
    			 publisher_api_.SetVideoEncoderSpecialInt32Option(publisher_handle_, "usage_type", btn_check_openh264_ppt_usage_type_.GetCheck() == BST_CHECKED ? 1 : 0);
    			 publisher_api_.SetVideoEncoderSpecialInt32Option(publisher_handle_, "rc_mode", btn_check_openh264_rc_bitrate_mode_.GetCheck() == BST_CHECKED ? 1 : 0);
    			 publisher_api_.SetVideoEncoderSpecialInt32Option(publisher_handle_, "enable_frame_skip", btn_check_openh264_frame_skip_.GetCheck() == BST_CHECKED ? 1 : 0);
    		}
    		else
    		{
    			publisher_api_.SetVideoEncoderQPMax(publisher_handle_, -1);
    			publisher_api_.SetVideoEncoderQPMin(publisher_handle_, -1);
    		}
    	}
    
    
    	// 音频相关设置
    	if ( BST_CHECKED == btn_check_auido_mic_input_.GetCheck() )
    	{
    		auto count = combox_auido_input_devices_.GetCount();
    		if (count != CB_ERR && count > 0)
    		{
    			auto cur_sel = combox_auido_input_devices_.GetCurSel();
    			if (cur_sel != CB_ERR)
    			{
    				publisher_api_.SetAuidoInputDeviceId(publisher_handle_, cur_sel);
    			}
    		}
    	}
    
    	// 只采集扬声器时做静音补偿
    	if ( BST_CHECKED != btn_check_auido_mic_input_.GetCheck()
    		&& BST_CHECKED == btn_check_auido_speaker_input_.GetCheck() )
    	{
    		publisher_api_.SetCaptureSpeakerCompensateMute(publisher_handle_, 1);
    	}
    
    	if ( BST_CHECKED == btn_check_speex_encoder_.GetCheck())
    	{
    		publisher_api_.SetPublisherAudioCodecType(publisher_handle_, 2);
    
    		publisher_api_.SetPublisherSpeexEncoderQuality(publisher_handle_, GetIntValueFromEdit(&edit_speex_quality_));
    	}
    	else
    	{
    		publisher_api_.SetPublisherAudioCodecType(publisher_handle_, 1);
    	}
    
    	if ( BST_CHECKED == btn_check_auido_mic_input_.GetCheck()
    		|| BST_CHECKED == btn_check_auido_speaker_input_.GetCheck())
    	{
    		if (BST_CHECKED == btn_check_set_mute_.GetCheck())
    		{
    			publisher_api_.SetMute(publisher_handle_, 1);
    		}
    	}
    
    	if ( BST_CHECKED == btn_check_echo_cancel_.GetCheck() )
    	{
    		publisher_api_.SetEchoCancellation(publisher_handle_, 1, GetIntValueFromEdit(&edit_echo_delay_));
    	}
    	else
    	{
    		publisher_api_.SetEchoCancellation(publisher_handle_, 0, 0);
    	}
    
    	if ( BST_CHECKED == btn_check_noise_suppression_.GetCheck() )
    	{
    		publisher_api_.SetNoiseSuppression(publisher_handle_, 1);
    	}
    	else
    	{
    		publisher_api_.SetNoiseSuppression(publisher_handle_, 0);
    	}
    
    	if ( BST_CHECKED == btn_check_agc_.GetCheck() )
    	{
    		publisher_api_.SetAGC(publisher_handle_, 1);
    	}
    	else
    	{
    		publisher_api_.SetAGC(publisher_handle_, 0);
    	}
    
    	if (BST_CHECKED == btn_check_vad_.GetCheck())
    	{
    		publisher_api_.SetVAD(publisher_handle_, 1);
    	}
    	else
    	{
    		publisher_api_.SetVAD(publisher_handle_, 0);
    	}
    
    	if (BST_CHECKED == btn_check_auido_mic_input_.GetCheck()
    		&& BST_CHECKED == btn_check_auido_speaker_input_.GetCheck())
    	{
    		publisher_api_.SetInputAudioVolume(publisher_handle_, 0, GetDoubleValueFromEdit(&edit_audio_input_volume_));
    		publisher_api_.SetInputAudioVolume(publisher_handle_, 1, GetDoubleValueFromEdit(&edit_audio_speaker_input_volume_));
    	}
    	else if (BST_CHECKED == btn_check_auido_mic_input_.GetCheck())
    	{
    		publisher_api_.SetInputAudioVolume(publisher_handle_, 0, GetDoubleValueFromEdit(&edit_audio_input_volume_));
    	}
    	else if (BST_CHECKED == btn_check_auido_speaker_input_.GetCheck())
    	{
    		publisher_api_.SetInputAudioVolume(publisher_handle_, 0, GetDoubleValueFromEdit(&edit_audio_speaker_input_volume_));
    	}
    }

    接下来,设置preview回调:

    	publisher_api_.SetVideoPreviewImageCallBack(publisher_handle_, NT_PB_E_IMAGE_FORMAT_RGB32, GetSafeHwnd(), &NT_PB_SDKVideoPreviewImageHandle);

    然后,调用preview接口:

    void CSmartPublisherDemoDlg::OnBnClickedButtonStartPreview()
    {
    	if ( BST_CHECKED == btn_check_window_input_.GetCheck() )
    	{
    		if (nullptr == cur_sel_capture_window_)
    		{
    			AfxMessageBox(_T("请先下拉选择采集窗口"));
    			return;
    		}
    	}
    
    	if ( publisher_handle_ == NULL )
    	{
    		if (!OpenPublisherHandle())
    		{
    			return;
    		}
    	}
    
    	if ( publisher_handle_count_ < 1 )
    	{
    		SetCommonOptionToPublisherSDK();
    	}
    
    	ASSERT(publisher_handle_ != NULL);
    
    	publisher_api_.SetVideoPreviewImageCallBack(publisher_handle_, NT_PB_E_IMAGE_FORMAT_RGB32, GetSafeHwnd(), &NT_PB_SDKVideoPreviewImageHandle);
    	
    	if (NT_ERC_OK != publisher_api_.StartPreview(publisher_handle_, 0, NULL))
    	{
    		if ( 0 == publisher_handle_count_ )
    		{
    			publisher_api_.Close(publisher_handle_);
    			publisher_handle_ = NULL;
    		}
    
    		AfxMessageBox(_T("预览失败, 请确保选择了视频采集选项"));
    		return;
    	}
    
    	publisher_handle_count_++;
    
    	btn_preview_.EnableWindow(FALSE);
    	btn_stop_preview_.EnableWindow(TRUE);
    
    	if ( 1 == publisher_handle_count_ )
    	{
    		if (BST_CHECKED == btn_check_desktop_input_.GetCheck())
    		{
    			btn_choose_screen_region_.SetWindowTextW(L"移动屏幕区域");
    		}
    
    		btn_check_dxgi_screen_capturer_.EnableWindow(FALSE);
    		check_capture_layered_window_.EnableWindow(FALSE);
    
    		btn_check_wr_way_capture_window_.EnableWindow(FALSE);
    
    		btn_check_desktop_camera_switch_.EnableWindow(FALSE);
    		btn_check_camera_overlay_to_desktop_.EnableWindow(FALSE);
    		btn_check_desktop_overlay_to_camera_.EnableWindow(FALSE);
    
    		btn_add_image_watermark_.EnableWindow(FALSE);
    
    		if (BST_CHECKED == btn_check_desktop_camera_switch_.GetCheck()
    			|| BST_CHECKED == btn_check_camera_overlay_to_desktop_.GetCheck()
    			|| BST_CHECKED == btn_check_desktop_overlay_to_camera_.GetCheck())
    		{
    
    		}
    		else
    		{
    			btn_check_desktop_input_.EnableWindow(FALSE);
    			btn_check_scale_desktop_.EnableWindow(FALSE);
    			edit_desktop_scale_.EnableWindow(FALSE);
    
    			btn_check_camera_input_.EnableWindow(FALSE);
    			btn_check_window_input_.EnableWindow(FALSE);
    		}
    
    		DisableAuidoInputControl();
    	}
    
    	CreatePreViewWindow();
    	ShowPreViewWindow(true);
    }
    

    NT_PB_SDKVideoPreviewImageHandle相关回调实现:

    extern "C"  NT_VOID NT_CALLBACK NT_PB_SDKVideoPreviewImageHandle(NT_HANDLE handle, NT_PVOID user_data,
    	const NT_PB_Image* image)
    {
    	if ( image != nullptr && image->format_ == NT_PB_E_IMAGE_FORMAT_RGB32
    		&& image->width_ > 0 && image->height_ > 0
    		&& image->plane_[0] != nullptr
    		&& image->stride_[0] > 0
    		)
    	{
    		std::unique_ptr<nt_pb_rgbx_image> rgbx_image(new nt_pb_rgbx_image());
    
    		rgbx_image->width_  = image->width_;
    		rgbx_image->height_ = image->height_;
    		rgbx_image->stride_ = image->stride_[0];
    		rgbx_image->size_   = image->stride_[0] * image->height_;
    
    		rgbx_image->data_.reset(new NT_BYTE[rgbx_image->size_]);
    
    		if ( rgbx_image->data_ )
    		{
    			memcpy(rgbx_image->data_.get(), image->plane_[0], rgbx_image->size_);
    
    			HWND hwnd = reinterpret_cast<HWND>(user_data);
    			if (hwnd != NULL && ::IsWindow(hwnd))
    			{
    				::PostMessage(hwnd, WM_USER_PB_SDK_PREVIEW_RGBX_IMAGE, (WPARAM)(rgbx_image.release()), 0);
    			}
    		}
    	}
    
    	/*std::ostringstream ss;
    
    	ss << "OnPreviewImage handle:" << handle << " w=" << image->width_
    	<< " h=" << image->height_
    	<< " format=" << image->format_ << " \r\n";
    
    	OutputDebugStringA(ss.str().c_str());*/
    }

    这里通过调用封装后的nt_pb_ui_preview_wnd, 来完成本地实时预览:

    LRESULT CSmartPublisherDemoDlg::OnSDKPreviewRGBXImage(WPARAM wParam, LPARAM lParam)
    {
    	nt_pb_rgbx_image* rgbx_image = (nt_pb_rgbx_image*)(wParam);
    
    	if ( rgbx_image != nullptr )
    	{
    		std::shared_ptr<nt_pb_rgbx_image> sp_rgbx_image(rgbx_image);
    
    		preview_wnd_.OnRGBXImage(sp_rgbx_image);
    	}
    
    	return S_OK;
    }

    具体实现如下:

    void nt_pb_ui_preview_wnd::OnRGBXImage(const std::shared_ptr<nt_pb_rgbx_image>& sp_image)
    {
    	rgbx_image_ = sp_image;
    
    	if (m_hWnd != NULL && ::IsWindow(m_hWnd) && ::IsWindowVisible(m_hWnd))
    	{
    		InvalidateRect(NULL, FALSE);
    	}
    }

    OnPaint()实时刷新数据:

    void nt_pb_ui_preview_wnd::OnPaint()
    {
    	CPaintDC dc(this); // device context for painting
    	// TODO: Add your message handler code here
    	// Do not call CWnd::OnPaint() for painting messages
    
    	if ( IsIconic() )
    	{
    		return;
    	}
    
    	CRect rc_client(0, 0, 0, 0);
    	GetClientRect(rc_client);
    
    	if ( rc_client.IsRectNull()
    		|| rc_client.IsRectEmpty() )
    	{
    		return;
    	}
    
    	auto mem_dc = ::CreateCompatibleDC(dc.GetSafeHdc());
    	auto mem_bitmap = ::CreateCompatibleBitmap(dc.GetSafeHdc(), rc_client.Width(), rc_client.Height());
    	::SelectObject(mem_dc, mem_bitmap);
    
    	HBRUSH brush = ::CreateSolidBrush(RGB(238, 243, 250));
    	::FillRect(mem_dc, &rc_client, brush);
    	::DeleteObject(brush);
    
    	DrawImage(mem_dc, rc_client);
    
    	::BitBlt(dc.GetSafeHdc(),
    		0, 0,
    		rc_client.Width(), rc_client.Height(),
    		mem_dc,
    		0, 0,
    		SRCCOPY);
    
    	::DeleteObject(mem_bitmap);
    
    	::DeleteDC(mem_dc);
    }

    DrawImage()封装实现

    void nt_pb_ui_preview_wnd::DrawImage(HDC hdc, const CRect& rc_client)
    {
    	ASSERT(hdc != NULL);
    	ASSERT(!rc_client.IsRectNull());
    	ASSERT(!rc_client.IsRectEmpty());
    
    	if ( !rgbx_image_ )
    		return;
    
    	if (rc_client.Width() < 100 || rc_client.Height() < 100)
    		return;
    
    	if (draw_api_ == nullptr)
    		return;
    
    	NT_PB_Image image;
    
    	memset(&image, 0, sizeof(image));
    	
    	image.cb_size_ = sizeof(image);
    	image.format_  = NT_PB_E_IMAGE_FORMAT_RGB32;
    	image.width_   = rgbx_image_->width_;
    	image.height_  = rgbx_image_->height_;
    	image.timestamp_ = 0;
    
    	image.plane_[0]		 = rgbx_image_->data_.get();
    	image.stride_[0]	 = rgbx_image_->stride_;
    	image.plane_size_[0] = rgbx_image_->size_;
    
    	auto limit_w = rc_client.Width() - 8;
    	auto limit_h = rc_client.Height() - 8;
    
    	auto  d_w = 0, d_h = 0;
    
    	if ( rgbx_image_->width_ <= limit_w && rgbx_image_->height_ <= limit_h )
    	{
    		d_w = rgbx_image_->width_;
    		d_h = rgbx_image_->height_;
    	}
    	else
    	{
    		CalScaleSize(limit_w, limit_h, rgbx_image_->width_, rgbx_image_->height_, d_w, d_h);
    	}
    
    	if ( d_w > 0 && d_h > 0 )
    	{
    		auto d_x = rc_client.Width()/2 - d_w/2;
    		auto d_y = rc_client.Height()/2 - d_h/2;
    	   
    		draw_api_->Draw(hdc, d_x, d_y,
    			d_w, d_h,
    			0, 0,
    			rgbx_image_->width_, rgbx_image_->height_,
    			&image);
    	}
    }

    停止预览

    调用StopPreview()即可。

    void CSmartPublisherDemoDlg::OnBnClickedButtonStopPreview()
    {
    	publisher_handle_count_--;
    	publisher_api_.StopPreview(publisher_handle_);
    
    	if (0 == publisher_handle_count_)
    	{
    		publisher_api_.Close(publisher_handle_);
    		publisher_handle_ = NULL;
    	}
    
    	btn_preview_.EnableWindow(TRUE);
    	btn_stop_preview_.EnableWindow(FALSE);
    
    	if (0 == publisher_handle_count_)
    	{
    		if (BST_CHECKED == btn_check_desktop_input_.GetCheck())
    		{
    			btn_choose_screen_region_.SetWindowTextW(L"选择屏幕区域");
    		}
    
    		btn_check_dxgi_screen_capturer_.EnableWindow(TRUE);
    		check_capture_layered_window_.EnableWindow(TRUE);
    
    		btn_check_wr_way_capture_window_.EnableWindow(TRUE);
    
    		btn_desktop_camera_switch_.SetWindowTextW(L"切换到摄像头");
    		btn_disable_image_watermark_.SetWindowTextW(L"停止水印");
    		btn_disable_camera_overlay_.SetWindowTextW(L"停止叠加摄像头");
    		btn_disable_desktop_overlay_.SetWindowTextW(L"停止叠加屏幕");
    
    		btn_check_desktop_camera_switch_.EnableWindow(TRUE);
    		btn_check_camera_overlay_to_desktop_.EnableWindow(TRUE);
    		btn_check_desktop_overlay_to_camera_.EnableWindow(TRUE);
    
    		btn_add_image_watermark_.EnableWindow(TRUE);
    
    		if (BST_CHECKED == btn_check_desktop_camera_switch_.GetCheck()
    			|| BST_CHECKED == btn_check_camera_overlay_to_desktop_.GetCheck()
    			|| BST_CHECKED == btn_check_desktop_overlay_to_camera_.GetCheck())
    		{
    
    		}
    		else
    		{
    			btn_check_desktop_input_.EnableWindow(TRUE);
    			btn_check_scale_desktop_.EnableWindow(TRUE);
    			edit_desktop_scale_.EnableWindow(TRUE);
    
    			btn_check_camera_input_.EnableWindow(TRUE);
    			btn_check_window_input_.EnableWindow(TRUE);
    		}
    
    		EnableAuidoInputControl();
    	}
    
    	ShowPreViewWindow(false);
    }

     

    展开全文
  • 首先本人学习了一点网络通信的知识和c++以及qt的小知识,关于最近比较...当然懂了这个你只需要再学会摄像头的视频采集图像的压缩(装库)就可以进行远程监控了。 首先我在网上搜了搜这方面的知识,好像并不多,关

    关于最近比较火的物联网视频监控项目,在这里给大家分享下图片传输这一块,首先客户端显示是在Windows下Qt中,服务器是在linux系统ubuntu中,服务端打开本地两张图片循环发送给客户端Qt进行显示。有了图片传输只需要再学会摄像头的视频采集和图像的压缩(装库)就可以进行远程监控了。
    首先我在网上搜了搜这方面的知识,好像并不多,关于qt显示图片的倒还是比较多的,但网络传输的就比较少了。好了废话不多说,先看服务器的代码(PS:当时是截的图片,源代码也找不到了):为了方便直接写在一个文件里面了
    首先头文件这里写图片描述然后创建套接字绑定监听接受等等套路:看图这里写图片描述没有写注释相信大家都能看懂,然后是发图片的代码:这里写图片描述重点来了这里写图片描述相信大家也知道怎么传,这里主要说一下封包的问题,大概就是自定义协议嘛,服务器得让客户端知道我发给你的图片有多大,你按照我给你发的大小来接收图片就好了,在这里方法有很多种,说两种吧,一种是封一个固定大小的包,包头有固定字节大小的表示后面所跟的文件大小,整体封装在一个字符数组里发送,我为了偷懒所以采用的这种办法,我打开的两张图片一张50多k一样30多k,而我拿了一个60k的包来装,所以问题来了,有点空间浪费,原因还是图片大小不一造成的嘛,如果是做视频采集那个的话,图像大小相距不多也还是可以,当然这样做的优点就是我客户端每次只需要收固定包大小就好了。另一方法当然就是大小和图片分开传不打包,当然大小后面紧跟着就是图片信息,假如吧我拿10个字节封装成大小的包先发过去,10位数表示的大小也该有那么大了,感兴趣的自己算,当然可能用不到,但这点小空间浪费问题不大,然后这10个字节后仅跟着就发图片数据了,但qt这边接收稍微麻烦了一点点,带会儿看qt代码的时候再说。当然还有其他的方法,想封装结构体什么的我不太擅长,也没数组好用。好,服务器这边的代码相信大家都没有什么问题,毕竟我也只是有一点点基础的,这代码也就是有一点点基础的人写的,大牛们不要介意。
    然后在看qt这边的吧,首先申明我是新手,用的也是图形化界面,对象也是直接定义的,没有去new出来,新手嘛为了图简单就这样了。
    先看h文件,qt这边会给大家写注释的。这里写图片描述注释给大家写了,再来看对应源文件;
    这里写图片描述注释相信大家能理解,下面是重点了,收包显示
    先上图
    这里写图片描述图片上注释写的很清楚了,待会上效果图片,在这说一个前面提到的第二种封包的(这里可以参考后面毕设文章里的封包和接收,具体应该是第三篇里),我也写点伪代码吧上图:
    这里写图片描述上面写的一点伪代码,思路相信大家都知道了,好了现在看结果
    linux下图片:
    这里写图片描述这里只打开了两张图片循环发送,可以当gif动图了嘛,好了看效果(这里明天再补上,今晚先弄到这里(主要图片没有截哈哈,大家原谅一下))。今天把效果图补上,应该录个屏的,这里就截了两张图了;
    第一张
    第二张
    效果就这样了。请大牛勿喷。
    由于源代码或许已经找不到了,所以未有把截图替换成代码,抱歉。
    详细的设计在我的graduation design里面有。

    展开全文
  • 你只需在TWAIN接口写几行代码,就可以用兼容TWAIN的扫描仪扫描文档或从数码相机/采集卡中获取图像。然后用户可以编辑图像并将图像保存多种格式,用户可保存图像到远程数据库或者SharePoint。这个TWAIN控件还支持上传...

    Dynamic Web TWAIN是一个专为Web应用程序设计的TWAIN扫描识别控件。你只需在TWAIN接口写几行代码,就可以用兼容TWAIN的扫描仪扫描文档或从数码相机/采集卡中获取图像。然后用户可以编辑图像并将图像保存多种格式,用户可保存图像到远程数据库或者SharePoint。这个TWAIN控件还支持上传和处理本地图像。

                                        点击下载Dynamic Web TWAIN最新版

    本篇文章将帮助你了解在最终用户的计算机上应该安装或部署Resources文件夹中的哪些文件,才能在Web应用程序中支持文档扫描和保存。

    在v14.2+中,为了获得更好的用户体验,在Windows,包括ActiveX上,Dynamic Web TWAIN相关文件随Dynamsoft Service一起安装,包括核心扫描库和PDF光栅化等。

    *适用于在Windows上使用IE,Edge,Chrome或Firefox的最终用户(Windows XP / 7/8/2008 / 2012/2016和10;32位和64位)

    • DynamsoftServiceSetupTrial.msi / DynamsoftServiceSetup.msi
    • DynamsoftServiceSetupTrialx64.msi / DynamsoftServiceSetupx64.msi

    需要在最终用户计算机上手动安装此Dynamsoft Service。对于受控环境,你还可以使用MSI以静默方式将服务部署到所有最终用户计算机,请访问:https://developer.dynamsoft.com/dwt/kb/2866

    虽然提供了32位和64位安装程序,但默认情况下仅使用32位安装程序

    *适用于使用Safari,Chrome或Firefox on Mac OS(OS X 10.6.8+)的最终用户

    • DynamsoftServiceSetup.pkg / DynamsoftServiceSetupTrial.pkg

    需要在最终用户计算机上手动安装此Dynamsoft Service以及Dynamic Web TWAIN相关文件。

    *适用于在Linux上使用Chrome或Firefox的最终用户(Ubuntu 12.0.4 +,Debian 8 +,Fedora 24 +,mint 18.3; 64位)

    • DynamsoftServiceSetup.rpm or DynamsoftServiceSetupTrial.rpm
    • DynamsoftServiceSetup.deb or DynamsoftServiceSetupTrial.deb

    需要在Debian / Ubuntu / mint或Fedora最终用户计算机以及Dynamic Web TWAIN相关文件上手动安装此Dynamsoft Service。


    转载于:https://juejin.im/post/5c25e8e4f265da613356a65d

    展开全文
  • Windows95下多线程编程技术及其实现 笔者最近在开发基于Internet网上的可视电话过程中碰到了这样一个问题, 即在基于In ternet网上的可视电话系统中,同时要进行语音采集语音编 译码图像采集图像编译码语音和图像码流...
  • 第13章介绍电视图像采集卡的工作原理及编程方法。读者可到http://www.tupwk.com.cn/downpage/index.asp下载本书演示程序的全部源代码、相关的字库文件以及所需的图像。 本书可作为图像处理编程人员的参考书,以及少...
  • OpenCV在Ubuntu下的图像编程

    千次阅读 2020-10-28 23:28:37
    文章目录一、如何在Ubuntu下安装opencv二、使用opencv打开一张图片三、使用opencv打开摄像头四、使用opencv打开一个视频文件五、通过摄像头采集图像并压缩成视频六、参考???? 一、如何在Ubuntu下安装opencv 具体...
  • 笔者最近在开发基于Internet网上的可视电话过程中碰到了这样一个问题,即在基于In ternet网上的可视电话系统中,同时要进行语音采集、语音编译码、图像采集、图像编译码、语音和图像码流的传输,所有这些工作,都要并行...
  • 基于Socket和OpenCV的实时视频传输(On Windows

    万次阅读 热门讨论 2016-08-14 14:56:33
    由一台PC(Client客户端)采集摄像头图像后经Socket传输到另一台PC(Server服务器)再显示出来。 这一篇介绍在Windows上的实现,在下一篇讲解在Linux上的实现。 环境: Server: Windows 10 + OpenCV...
  • 1、安装“安装包”目录下的“setup.exe”文件,按照提示安装影像采集ActiveX工具(Windows7及以上系统C盘存在保护机制,建议将控件安装到D盘)。 2、打开IE浏览器(如果是Windows7或Windows8系统,IE需要用管理员...
  • 地理信息系统( GIS)、全球定位系统( GPS)的广泛应用使人们享受到了基于位置服务所带来的诸多便利。传统G IS 是以地图为可视化主要手段, 然而人类获取信息的70%来自于视觉, 因此将地理位置信息和视频信息有机结合...
  • 地理信息系统( GIS)、全球定位系统( GPS)的广泛应用使人们享受到了基于位置服务所带来的诸多便利。传统G IS 是以地图为可视化主要手段, 然而人类获取信息的70%来自于视觉, 因此将地理位置信息和视频信息有机结合...
  • mjpg-streamer服务器移植

    千次阅读 2017-03-30 16:58:17
    “MJPG-streamer”,是用户从webcam摄像头采集图像,并以流的形式通过基于IP的网络传输到浏览器图Firefox,Cambozola,VlC播放器,Windows的移动设备或者其他用户浏览器的移动设备,她可以利用某系webcam的硬件压缩...
  • 兼容 Windows Script Components 并提供编译支持 支持 WAP、WML 构建 Web Service 和 Internet 应用程序  迷你IIS服务器 提供一套完整的脚本语言开发环境,提供超轻量脚本引擎和极快的 Web Server,桌面应用对象...
  • 2、然后找1653到Windows Image Acquisition (WIA)服务(为扫描回仪和照相机提答供图像采集服务);3、选中服务点右键,点启动。如果启动成功就去设备和打印机,右键打印机图标扫描选项应该已经出来了,如果启动不成功...
  • 提出一种基于ARM嵌入式开发平台视频监控的实现...通过V4L2在Linux下构建视频图像采集和显示,然后使用servfox和spcaview构建视频服务器,系统可在Linux和Windows操作系统下通过窗口或者网页进行视频监控和图像抓拍。
  • 通过V4L2 在Linux 下构建视频图像采集和显示,然后使用servfox 和spcaview 构建视频服务器,系统可在Linux 和Windows 操作系统下通过窗口或者网页进行视频监控和图像抓拍。测试表明系统的监控图像清晰,并具有体积小...
  • 摘要:该文提出了一种在门禁系统中利用人脸识别技术与指纹识别技术相结合进行身份验证的设计方案。实验表明,结合两种技术将会提高身份识别的安全性和有效性,能有效地解决传统门禁系统的不足... 图像采集端利用Direct
  • 摘要:该文提出了一种在门禁系统中利用人脸识别技术与指纹识别技术相结合进行身份验证的设计方案。实验表明,结合两种技术将会提高身份识别的安全性和有效性,能有效地解决传统门禁系统的不足... 图像采集端利用Direct
  • 本文介绍的智能小车可移动视频监控系统,以“飞思卡尔杯”智能小车竞赛提供的车模装置为基础,利用ARM芯片S3C2440A控制图像采集、网络传输、速度采集干扰小的模块,利用FPGA芯片控制电机驱动、舵机控制、电量采集...
  • 蓝韵超声影像管理解决方案是为广大医院量身制作,集病人信息登记与预约、图像采集与处理、诊断报告编辑与打印、病历查询与检索、统计分析与科室管理、数据备份与恢复、HIS系统互联与临床发布等功能于一体的综合信息...
  • OpenCV结合socket进行实时视频传输(TCP协议)

    万次阅读 多人点赞 2017-08-12 22:32:54
    一、概述内容:由Client客户端采集摄像头图像后经Socket传输到Server服务器端再显示出来。本实验在同一台电脑上实验,即运行服务器程序,又跑客户端程序,也就是说通过socket编程来实现数据的自发自收,这一步通过了...

空空如也

空空如也

1 2 3 4 5 6
收藏数 101
精华内容 40
关键字:

windows图像采集服务