最近做了个大头帖软件,正在策划制作一套MTV合成软件,刚完成摄像头与MTV融合播放,可以去掉某一视频的特定颜色,技术实现上差不多解决了,还有点不完美的地方,特来求段代码,就是把某一范围内的颜色替换为特定的一种颜色.要求是,来源颜色是蓝色和其他颜色,但这个蓝色不是纯蓝色,有相间色,我要的代码就是按这个蓝色范围替换颜色为纯蓝.我目前的测试代码是这样的,我都替换为了黑色,给我的代码可别这样,否则不收:
      BITMAP.PixelFormat := PF24BIT;
      for y := 0 to BitMap.Height - 1 do
      begin
        P := BitMap.ScanLine[y];
        for x := 0 to BitMap.Width - 1 do
        begin
          if (p[x * 3] <= 70) then
            p[x * 3] := 0;              //蓝
          if (p[x * 3 + 1] <= 70) then
            P[x * 3 + 1] := 0;          //绿
          if (p[x * 3 + 2] <= 70) then
            P[x * 3 + 2] := 0;          //红
          { if (p[x * 3] <= 100) and
             (p[x * 3 + 1] <= 100) and
             (p[x * 3 + 2] <= 100) then
           begin
             p[x * 3] := 0;              //蓝
             P[x * 3 + 1] := 0;          //绿
             P[x * 3 + 2] := 0;          //红
           end;          }
        end;
      end;这个算法是相当简陋的,但速度很不错,同志们,别忘了保证速度.谢过..!

解决方案 »

  1.   

    没想出啥好算法只是把部分代码换成汇编了
    不知道速度能提高多少
    没测试,呵呵procedure SwapRGB(data: Pointer;W:Integer);
    asm
      push ebx;  mov ebx, eax;
      mov ecx, W;
    @@loopW :
      mov al,$FF;
      mov [ebx+2],al;
      mov al,0;
      mov [ebx+1],al;
      mov al,0;
      mov [ebx+0],al;
      add ebx,3;
      dec ecx;
     jnz @@loopW;  pop ebx;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var i:integer;
    begin
      with Image1.Picture.Bitmap do
      begin
      for i:=0 to Height-1 do
        SwapRGB(ScanLine[i],width);
      Image1.Refresh;
      end;
    end;
      

  2.   

    昏,我狂晕中,算了......,我只是想找段"要求是,来源颜色是蓝色和其他颜色,但这个蓝色不是纯蓝色,有相间色,我要的代码就是按这个蓝色范围替换颜色为纯蓝."符合这样要求的现成的代码,而不是优化偶写的那段,不过myling 的代码我收了,不说了,不说了,结帖结帖,这几天我发了近千分的帖子,再来的帮我鄙视一下这个贴  http://community.csdn.net/Expert/TopicView.asp?id=3611060顺便帖个生成蓝色的范围
    var
      r, g, b           : integer;
      {  w, h              : integer;   }
      bitmap            : tbitmap;
      x, y              : integer;
      P                 : pbyteArray;
    begin
      //建立16k色带[蓝色]
      bitmap := tbitmap.Create;
      bitmap.Width := image1.Width;
      bitmap.Height := image1.Height;
      BITMAP.PixelFormat := PF24BIT;
      for y := 0 to BitMap.Height - 1 do
      begin
        P := BitMap.ScanLine[y];
        r := 0;
        g := 0;
        b := 0;
        for x := 0 to BitMap.Width - 1 do
        begin
          p[x * 3] := b;                    //蓝b
          P[x * 3 + 1] := g;                //绿g
          P[x * 3 + 2] := r;                //红r
          if b >= 255 then
          begin
            Inc(r);
            inc(g);
          end
          else
            inc(b);
        end;
      end;
      image1.Picture.Bitmap.Assign(bitmap);
      image1.Picture.Bitmap.PixelFormat := PF24BIT;
      bitmap.free;
    end;
      

  3.   

    对了,myling ,最近有什么游戏作品吗?
      

  4.   

    没有
    最近好浮躁玩疯了打算过一阵子好好看看C++,学学DX继续找工作
      

  5.   

    这么说吧,就是象电影不是要做合成吗?通常人物背景是用蓝色,再合成到另外的视频之上后蓝色都看不到,只剩下人物了,这样就可以了;但摄像头拍摄到蓝色不是纯蓝色,我肯定不能只是简单的设置透明标志是clblue ,那样的话没有起到任何效果,因为是蓝色的相间色,必须全部处理掉,有点类似photoshop的魔棒的功能,选择颜色范围并允许容差.再把这些颜色都换为标准的纯蓝,这样就可以透明掉了.C++我也准备开始学习,也是学dx部分,也在找工作,怎么我跟你一样嘛!
      

  6.   

    呵呵
    原来这么复杂,偶想的太简单了还不完全一样,我现在是骑驴找马
    不敢完全待业,经济来源一断,在上海活不下去了就
    性欲低没关系阿,我以前有半年左右的时间性欲分是1分:P
    那时候郁闷阿,受尽了其他斑猪的气
    谁看我不顺眼,就将我正法,还得我不停的提交FAQ活过来。哈哈
      

  7.   

    pfpf,1分都可以翻身,我99分-1分却没机会,这个帖不象是能进faq的,期待下次有这样的机会:)
    你对directshow有兴趣吗,有机会一起研究;最近在家里嫌着想搞点产品出来
      

  8.   

    你说那个是不是就是把RGB的B值将近clBlue的像素转换成clBlue阿?那只能一个像素一个像素的判断吧?想不出啥好算法来还好大头贴的像素不算太多那段汇编改一下,加一下判断跳转也能实现关键是那个范围和容差不好掌握搞不好就把人家身上的颜色给转掉了
      

  9.   

    对DX了解不多
    看了各种版本的几个例子
    都看晕了俺还是对3D感兴趣
      

  10.   

    其实也好办,打开windows 调色板,看看蓝色周围的近视色都是些什么,写死的也写出来的,只是麻烦了点,把别人身上的替换掉那都没办法保证了,只能叫人家别穿蓝色衣服,带蓝色隐形眼睛;
    大头贴的花边透明色是纯色,所以就不存在这个问题了
      

  11.   

    我那是后来赶上好时候了arrir上台恢复性欲值,俺才恢复了,呵呵
      

  12.   

    var
      x, y              : integer;
      bitmap            : Tbitmap;
      p                 : pbyteArray;
    begin
      bitmap := Tbitmap.Create;
      bitmap.Assign(image1.Picture.Bitmap);
      BITMAP.PixelFormat := PF24BIT;
      for y := 0 to BitMap.Height - 1 do
      begin
        P := BitMap.ScanLine[y];
        for x := 0 to BitMap.Width - 1 do
        begin      if (p[x * 3] <= 255) then
            p[x * 3] := 255;                  //蓝      if (p[x * 3] = 255) and (p[x * 3 + 1] <= 150) then
            P[x * 3 + 1] := 0;              //绿      if (p[x * 3] = 255) and (p[x * 3 + 2] <= 150) then
            P[x * 3 + 2] := 0;              //红
        end;
      end; image1.Picture.Bitmap.Assign(bitmap);
      bitmap.Free;
    这样已经实现了屏蔽大部分蓝色的要求,只是不完美,亮蓝部分还不好控制,还是得找出这些交叉颜色的特定值;大头贴一般只看见脸部,而花边则是显示于面部之上,去掉花边透明色即可,不理会后面背景挡的那块布
      

  13.   

    补充一下,蓝色范围是        r 0..127
            g 0
            b 70..255        r 0
            g 0..127
            b 70..255        r 0..255
            g 0..255
            b 70..255准确的算法是这样的:procedure TForm1.Button1Click(Sender: TObject);
      function betWeen(a, b, c: variant): boolean;
      begin
        result := (a >= b) and (a <= c);
      end;var
      x, y              : integer;
      bitmap            : Tbitmap;
      p                 : pbyteArray;
      r, g, b           : byte;
    const
      rc                = 128;
    begin
      bitmap := Tbitmap.Create;
      bitmap.Assign(image1.Picture.Bitmap);
      BITMAP.PixelFormat := PF24BIT;
      for y := 0 to BitMap.Height - 1 do
      begin
        P := BitMap.ScanLine[y];
        for x := 0 to BitMap.Width - 1 do
        begin
          r := p[x * 3 + 2];
          g := p[x * 3 + 1];
          b := p[x * 3];
          {
            r 0..127
            g 0
            b 70..255        r 0
            g 0..127
            b 70..255        r 0..255
            g 0..255
            b 70..255
          }
          if ((r <= rc) and (g = 0) and betWeen(b, 70, 255)) or
            ((r = 0) and (g <= rc) and betWeen(b, 70, 255)) or
            ((r = rc) and (g <= 255) and (b = 255)) or
            ((r <= 255) and (g = rc) and (b = 255)) or
            (between(r, rc, 254) and between(g, rc, 254) and (b = 255)) or
            ((r <= rc) and (g <= rc) and (b = 255)) then
          begin
            p[x * 3] := 255;                //蓝
            P[x * 3 + 1] := 0;              //绿
            P[x * 3 + 2] := 0;              //红
          end;
        end;
      end;  image1.Picture.Bitmap.Assign(bitmap);
      bitmap.Free;
    end;可以用photoshop画个蓝色渐变色,增加点其他颜色,用这段代码处理一下看看