2008-09-25 29 views
40

Tôi cần thực hiện giảm mắt đỏ cho một ứng dụng tôi đang thực hiện.Thuật toán giảm mắt đỏ

Googling chủ yếu cung cấp liên kết đến các sản phẩm thương mại của người dùng cuối.

Bạn có biết thuật toán giảm mắt đỏ tốt có thể được sử dụng trong ứng dụng GPL không?

Trả lời

43

Tôi đến muộn với bữa tiệc ở đây nhưng đối với những người tìm kiếm trong tương lai tôi đã sử dụng thuật toán sau cho ứng dụng cá nhân tôi đã viết.

Trước hết, vùng cần giảm được người dùng chọn và chuyển sang phương pháp giảm mắt đỏ làm điểm giữa và bán kính. Phương pháp lặp qua mỗi điểm ảnh trong vòng bán kính và làm việc tính toán sau đây:

//Value of red divided by average of blue and green: 
Pixel pixel = image.getPixel(x,y); 
float redIntensity = ((float)pixel.R/((pixel.G + pixel.B)/2)); 
if (redIntensity > 1.5f) // 1.5 because it gives the best results 
{ 
    // reduce red to the average of blue and green 
    bm.SetPixel(i, j, Color.FromArgb((pixel.G + pixel.B)/2, pixel.G, pixel.B)); 
} 

Tôi thực sự thích kết quả này bởi vì họ giữ cường độ màu, có nghĩa là phản xạ ánh sáng của mắt không bị giảm đi. (Điều này có nghĩa là đôi mắt giữ cho cái nhìn "sống động" của họ.)

+0

Bạn cũng có thể sử dụng công cụ chọn "cây đũa thần" ở điểm bấm có bán kính tối đa do người dùng cung cấp. – rafaelcastrocouto

3

Thuật toán đơn giản nhất, và vẫn là thuật toán rất hiệu quả sẽ bằng không trong R của RGB ba cho vùng quan tâm.

Màu đỏ biến mất, nhưng các màu khác được giữ nguyên.

Một mở rộng hơn nữa của thuật toán này có thể liên quan đến việc lấy ra giá trị R cho chỉ ba bộ mà màu đỏ là màu chủ đạo (R> G và R> B).

4

Nếu không có ai khác đưa ra câu trả lời trực tiếp hơn, bạn luôn có thể tải xuống the source code for GIMP và xem cách họ thực hiện.

6

Trước tiên, bạn cần phải tìm ra mắt! Cách tiêu chuẩn sẽ là chạy một máy dò cạnh và sau đó biến đổi Hough để tìm hai vòng tròn có cùng kích thước, nhưng có thể có các thuật toán dễ dàng hơn cho việc tìm kiếm các cụm pixel màu đỏ.

Sau đó, bạn cần phải quyết định những gì để thay thế chúng bằng, giả sử có đủ dữ liệu màu xanh lá cây/xanh lam trong hình ảnh bạn chỉ có thể bỏ qua kênh màu đỏ.

OpenCV là một thư viện miễn phí rất tốt để xử lý hình ảnh, nó có thể là quá mức cần thiết cho những gì bạn muốn - nhưng có rất nhiều ví dụ và một cộng đồng rất tích cực. Bạn cũng có thể tìm kiếm các thuật toán theo dõi đối tượng, theo dõi một đối tượng có màu trong một cảnh là một vấn đề rất nhỏ và phổ biến.

3

Dự án mã nguồn mở Paint.NET có triển khai trong C#.

+0

Tôi không nghĩ rằng nguồn có thể đạt được nữa. –

7

thư viện tuyệt vời để tìm mắt là openCV. nó rất phong phú với chức năng xử lý hình ảnh. xem thêm this giấy có tiêu đề "Tự động phát hiện mắt đỏ" từ Ilia V. Safonov.

2

Dưới đây là giải pháp thực hiện java

public void corrigirRedEye(int posStartX, int maxX, int posStartY, int maxY, BufferedImage image) { 
    for(int x = posStartX; x < maxX; x++) { 
     for(int y = posStartY; y < maxY; y++) { 

      int c = image.getRGB(x,y); 
      int red = (c & 0x00ff0000) >> 16; 
      int green = (c & 0x0000ff00) >> 8; 
      int blue = c & 0x000000ff; 

      float redIntensity = ((float)red/((green + blue)/2)); 
      if (redIntensity > 2.2) { 
       Color newColor = new Color(90, green, blue); 
       image.setRGB(x, y, newColor.getRGB()); 
      } 


     } 
    } 
} 

Là các thông số lấy từ hai hình chữ nhật được phát hiện bởi một ứng dụng như cv mở (điều này phải là một hình chữ nhật có liên quan đến vị trí mắt)

int posStartY = (int) leftEye.getY(); 

    int maxX = (int) (leftEye.getX() + leftEye.getWidth()); 
    int maxY = (int) (leftEye.getY() + leftEye.getHeight()); 

    this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image); 

    // right eye 

    posStartX = (int) rightEye.getX(); 
    posStartY = (int) rightEye.getY(); 

    maxX = (int) (rightEye.getX() + rightEye.getWidth()); 
    maxY = (int) (rightEye.getY() + rightEye.getHeight()); 

    this.corrigirRedEye(posStartX, maxX, posStartY, maxY, image); 
1

Đây là cách thực hiện đầy đủ hơn câu trả lời do Benry cung cấp:

using SD = System.Drawing; 

    public static SD.Image ReduceRedEye(SD.Image img, SD.Rectangle eyesRect) 
    { 
    if ( (eyesRect.Height > 0) 
     && (eyesRect.Width > 0)) { 
     SD.Bitmap bmpImage = new SD.Bitmap(img); 
     for (int x=eyesRect.X;x<(eyesRect.X+eyesRect.Width);x++) { 
      for (int y=eyesRect.Y;y<(eyesRect.Y+eyesRect.Height);y++) { 
       //Value of red divided by average of blue and green: 
       SD.Color pixel = bmpImage.GetPixel(x,y); 
       float redIntensity = ((float)pixel.R/((pixel.G + pixel.B)/2)); 
       if (redIntensity > 2.2f) 
       { 
       // reduce red to the average of blue and green 
       bmpImage.SetPixel(x, y, SD.Color.FromArgb((pixel.G + pixel.B)/2, pixel.G, pixel.B)); 
       pixel = bmpImage.GetPixel(x,y); // for debug 
       } 
      } 
     } 
     return (SD.Image)(bmpImage); 
    } 
    return null; 
    } 
Các vấn đề liên quan