經典影象顯著性檢測演算法 AC/HC/LC/FT

weixin_34321977發表於2018-12-25

1. LC演算法

參考論文:Visual Attention Detection in Video Sequences Using Spatiotemporal Cues Yun Zhai and Mubarak Shah. Page 4-5。

演算法原理部分見論文的第四第五頁。簡單說就是計算某個畫素在整個影象上的全域性對比度,即該畫素與影象中其他所有畫素在顏色上的距離之和作為該畫素的顯著值。

When viewers watch a video sequence, they are attracted not only by the interesting events, but also sometimes by the interesting objects in still images. This is referred as the spatial attention. Based on the psychological studies, human perception system is sensitive to the contrast of visual signals, such as color, intensity and texture. Taking this as the underlying assumption, we propose an e±cient method for computing the spatial saliency maps using the color statistics of images. The algorithm is designed with a linear computational complexity with respect to the number of image pixels. The saliency map of an image is built upon the color contrast between image pixels. The saliency value of a pixel in an image is defined as,

where the value of is in the range of [0; 255], and represent the color distance metric。

這裡如果直接用公式時間複雜度太高,所以用直方圖優化。下面是python版的程式碼實現:

def cal_dist(hist):
    dist = {}
    for gray in range(256):
        value = 0.0
        for k in range(256):
            value += hist[k][0] * abs(gray - k)
        dist[gray] = value
    return dist

def LC(image_gray):
    image_height = image_gray.shape[0]
    image_width = image_gray.shape[1]
    image_gray_copy = np.zeros((image_height, image_width))
    hist_array = cv2.calcHist([image_gray], [0], None, [256], [0.0, 256.0])  # 直方圖,統計影象中每個灰度值的數量
    gray_dist = cal_dist(hist_array)  # 灰度值與其他值的距離
    # print(gray_dist)
    for i in range(image_width):
        for j in range(image_height):
            temp = image_gray[j][i]
            image_gray_copy[j][i] = gray_dist[temp]
    image_gray_copy = (image_gray_copy - np.min(image_gray_copy)) / (np.max(image_gray_copy) - np.min(image_gray_copy))
    return image_gray_copy

if __name__ == '__main__':
    img = cv2.imread('***.jpg')
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    saliency_image = LC(image_gray)

2. HC演算法

參考論文: 2011 CVPR Global Contrast based salient region detection Ming-Ming Cheng

這篇論文有相關程式碼可以直接下載的,不過需要向作者索取解壓密碼 ,有pudn賬號的朋友可以直接在pudn上下載,不過那個下載的程式碼是用 opencv的低版本寫的,下載後需要自己配置後才能執行,並且似乎只有前一半能執行(顯著性檢測部分)。

論文提出了HC和RC兩種顯著性檢測的演算法,在本質上,HC和上面的LC沒有區別,但是HC考慮了彩色資訊,而不是像LC那樣只用畫素的灰度資訊,由於彩色影象最多有256 x 256 x 256種顏色,因此直接基於直方圖技術的方案不太可行了。但是實際上一幅彩色影象並不會用到那麼多種顏色,因此,作者提出了降低顏色數量的方案,將RGB各分量分別對映成12等份,則隱射後的圖最多隻有12 x 12 x 12種顏色,這樣就可以構造一個較小的直方圖用來加速,但是由於過渡量化會對結果帶來一定的瑕疵。因此作者又用了一個平滑的過程。 最後和LC不同的是,作者的處理時在Lab空間進行的,而由於Lab空間和RGB並不是完全對應的,其量化過程還是在RGB空間完成的。

3. FT演算法

參考論文: Frequency-tuned Salient Region Detection, Radhakrishna Achantay, Page 4-5, 2009 CVPR

這篇論文對顯著性檢測提出了以下5個指標:

  1. Emphasize the largest salient objects.

  2. Uniformly highlight whole salient regions.

  3. Establish well-defined boundaries of salient objects.

  4. Disregard high frequencies arising from texture, noise and blocking artifacts.

  5. Efficiently output full resolution saliency maps.

其求解過程非常簡單:

主要利用的是顏色特徵和亮度特徵。

  • 對影象img進行高斯濾波得到gfrgb;
  • 將影象imgrgb由RGB顏色空間轉換為LAB顏色空間imglab;
  • 對轉換後的影象imglab 的L,A,B三個通道的影象分別取均值得到lm,am,bm;
  • 計算顯著值,即對分別對三個通道的均值影象和濾波得到的影象取歐氏距離並求和;
  • 利用最大值對顯著圖歸一化。
def FT(src):
    lab = cv2.cvtColor(src,cv2.COLOR_BGR2LAB)
    gaussian_blur=cv2.GaussianBlur(src,(5,5),0)

    mean_lab = np.mean(lab,axis=(0,1))
    print(mean_lab.shape)

    salient_map = (gaussian_blur - mean_lab)*(gaussian_blur - mean_lab)
    salient_map = (salient_map-np.amin(salient_map))/(np.amax(salient_map)-np.amin(salient_map))
    
    return salient_map

4. AC演算法

參考論文:Salient Region Detection and Segmentation Radhakrishna Achanta, Francisco Estrada, Patricia Wils, and Sabine SÄusstrunk 2008 , Page 4-5

AC演算法也是Achanta等提出的,與FT演算法類似,只是在求歐式距離時使用的均值不再是整幅影象的均值,而是選取不同大小鄰域內的均值(三種大小)分別求取歐式距離,再相加得到。

這篇論文提出的演算法的思想用其論文的一句話表達就是:

saliency is determined as the local contrast of an image region with respect to its neighborhood at various scales.

演算法實現過程如下,選取三個鄰域大小分別為邊長為的正方形區域:

  1. 讀取影象,進行高斯濾波,並轉換到lab空間
  2. 分別求取該點附近鄰域lab空間的均值。以及鄰域lab空間的均值和鄰域lab空間的均值。
  3. 資料融合,


  4. 顯著圖

下面是C++版的實現:

void SalientRegionDetectionBasedonAC(Mat &src,int MinR2, int MaxR2,int Scale){
    Mat Lab;
    cvtColor(src, Lab, CV_BGR2Lab); 

    int row=src.rows,col=src.cols;
    int Sal_org[row][col];
    memset(Sal_org,0,sizeof(Sal_org));

    Mat Sal=Mat::zeros(src.size(),CV_8UC1 );

    Point3_<uchar>* p;
    Point3_<uchar>* p1;

    int val;
    Mat filter;

    int max_v=0;
    int min_v=1<<28;
    for (int k=0;k<Scale;k++){
        int len=(MaxR2 - MinR2) * k / (Scale - 1) + MinR2;
        blur(Lab, filter, Size(len,len ));
        for (int i=0;i<row;i++){
            for (int j=0;j<col;j++){
                p=Lab.ptr<Point3_<uchar> > (i,j);
                p1=filter.ptr<Point3_<uchar> > (i,j);
                
                val=sqrt( (p->x - p1->x)*(p->x - p1->x)+ (p->y - p1->y)*(p->y-p1->y) + (p->z - p1->z)*(p->z - p1->z) );

                Sal_org[i][j]+=val;
                if(k==Scale-1){
                    max_v=max(max_v,Sal_org[i][j]);
                    min_v=min(min_v,Sal_org[i][j]);
                }
            }
        }
    }

    cout<<max_v<<" "<<min_v<<endl;

    int X,Y;
    for (Y = 0; Y < row; Y++)
    {
        for (X = 0; X < col; X++)
        {
            Sal.at<uchar>(Y,X) = (Sal_org[Y][X] - min_v)*255/(max_v - min_v);        //    計算全圖每個畫素的顯著性
            //Sal.at<uchar>(Y,X) = (Dist[gray[Y][X]])*255/(max_gray);        //    計算全圖每個畫素的顯著性
        }
    }
    imshow("sal",Sal);
    waitKey(0);

}

參考連結:
https://cloud.tencent.com/developer/article/1011756
https://blog.csdn.net/cai13160674275/article/details/72991049

相關文章