《IMAGE BLOCKINESS EVALUATION BASED ON SOBEL OPERATOR》的Matlab实现

原文来自Perra C , Massidda F , Giusto D D . Image blockiness evaluation based on Sobel operator[C]// IEEE International Conference on Image Processing. IEEE, 2005.

Abstract: This article proposes a novel non-reference image blocking effect evaluation method, which uses the Sobel operator. The blocking effect score is the combination of the brightness changes of the edge pixels and the center pixel of the image block.
Detailed method:


  1. Convolve the masks Mx and My of the image I and the Sobel operator respectively: Mx=[-1,0,1;-2,0,2;-1,0,1] My=[-1,-2, -1;0,0,0;1,2,1]
    Get the edge images Dx and Dy:
    Dx=I Mx,Dy=I My where "*" represents the convolution operator

  2. Decompose Dx and Dy into several non-overlapping blocks of N*N size. When the block effect is generated by Jpeg compression, N is 8.

  3. For each N*N block (block after decomposition of Dx and Dy), do the following segmentation:
    Insert picture description here
    the area from left to right (the gray part in the figure) is marked as Ω1V, Ω1H, and Ω2. That is, each image block is located in All pixels in the first and last columns belong to Ω1V, and all pixels in the first and last rows belong to Ω1H, so that all pixels located in the second row to the second to last row, from the second column to the second to last column belong to Ω2.

  4. s1 and s2 are defined as follows:
    Insert picture description here
    where N1 and N2 are respectively the length of the sum on the right side, that is, the number of pixels in the outer circle and the number of pixels in the inner circle.

  5. Blockiness index S:
    Insert picture description here
    β takes 2.

Matlab implementation:

  1. First, convert the image I to a grayscale image, if I is already a grayscale image, do not operate:
if numel(size(I))>2 %如果不为灰度图像
    I=rgb2gray(I);
end
  1. Obtain the horizontal and vertical edge images dx, dy and the total edge image d through the conv2 function or edge. For the convenience of subsequent operations, the three edge images are converted to dobule type.
dx=double(edge(I,'Sobel','horizontal'));
dy=double(edge(I,'Sobel','vertical'));
d=double(edge(I,'Sobel'));
  1. Blocking: Let lenx and leny be the height and width of the block, the default setting is 8, num represents the number of blocks that have been divided, and the initial value is 0. Two-layer traversal is performed at leny units in the horizontal direction and lenx units in the vertical direction. The end points of the traversal are the width (size (I, 2)) and height (size (I, 1)) of the image. For vertical and horizontal traversal of current values ​​i and j, the position of the upper left pixel of the block in the original image is (i, j), the lower right pixel is (xend, yen), xend is the height and i+lenx-1 The minimum value, that is, the maximum height of the block is set to lenx, and the minimum depends on the distance to the bottom (because NN blocks, the bottom and right blocks may not meet the size of NN), and the same is true for yend. The result of block dx, dy, d is stored in the structure Block. At the end of the two-level traversal, the element number of Block is set to the variable num, which is expressed as the number of blocks.
lenx=8;
leny=8;
num=0;
for i=1:lenx:size(I,1)
    for j=1:leny:size(I,2)
        xend=min(i+lenx-1,size(I,1));
        yend=min(j+leny-1,size(I,2));
        num=num+1;
        Block.images_dx{num}=dx(i:xend,j:yend);
        Block.images_dy{num}=dy(i:xend,j:yend);
        Block.images_d{num}=d(i:xend,j:yend);
    end
end
Block.number=num;

4. Obtain the horizontal, vertical, and internal pixels: Taking the horizontal edge pixels as an example, write the function get_h() to return the coordinates of the horizontal edge pixels of the image block in the block. First get the size of the image block m*n, if m is greater than or equal to 2, it will return two rows (the first row and the last row), set the horizontal matrix to 2n (the number of pixels in two rows) 2, and each row is a two Meta coordinates. If it is 1, it means that there is only one row, then return this row, and set the horizontal to n 2.
First i traverse 1 to n, and store the coordinates (1,i) in the ith row of horizontal. If m is greater than or equal to 2, continue to store: i traverse 1 to n again, and store the coordinates
(n,i) in horizontal The i+nth line.

function [horizontal]=get_h(dy)
[m,n]=size(dy);
if m>=2
    horizontal=zeros(2*n,2);
else
    horizontal=zeros(n,2);
end
for i=1:n
    horizontal(i,1)=1;
    horizontal(i,2)=i;
end
if m>=2
    for i=1:n
    horizontal(i+n,1)=n;
    horizontal(i+n,2)=i;
    end
end
end

Write the function get_v() for vertical edge pixels in the same way. For the internal pixels, the size m n of the image block is obtained . Since the pixels on the top, bottom, left, and right sides are not counted, the number of internal pixels is (m-2) (n-2). In the vertical and horizontal directions, i and j are traversed from 2 to m-1 (or n-1) respectively, then the k-th row of the result is (i, j), where k is the current number of coordinates and is initialized to 0.

function [inner]=get_inner(d)
[m,n]=size(d);
inner=zeros((m-2)*(n-2),2);
k=0;
for i=2:m-1
    for j=2:n-1
        k=k+1;
        inner(k,1)=i;
        inner(k,2)=j;
    end
end
end
  1. i traverse from 1 to Block.number, take the current i-th dx, dy, d image block respectively, namely Block.images_dx{i}, the other two are the same, call the function written before, get the storage vertical, horizontal and The matrix of internal pixel coordinates is denoted as v, h, in. Then N1 is the sum of the height of v and the height of h (the sum of the point values ​​stored in the two matrices v and h), and N2 is the height of in (the number of points stored in the in matrix). For the current block, initialize s1 and s2 to 0, and take max_x, max_y, and max_in as the maximum value of the current block Block.images_dx{i}, Block.images_dy{i}, and Block.images_d{i}. j traverses all rows of v, according to the formula, s1 accumulates abs(Block.images_dx{i}(v(j,1),v(j,2)))/max_x, and traverses h and in in the same way. Finally, divide the value of s1 by N1 and store it in the s1 matrix of Block, and divide the value of s2 by N2 and store it in the s2 matrix.
for i=1:Block.number
    v=get_v(Block.images_dx{i});
    h=get_h(Block.images_dy{i});
    in=get_inner(Block.images_d{i});
    N1=size(v,1)+size(h,1);
    N2=size(in,1);
    s1=0;
    s2=0;
    max_x=max(max(Block.images_dx{i}));
    max_y=max(max(Block.images_dy{i}));
    max_in=max(max(Block.images_d{i}));
    for j=1:size(v,1)
        s1=s1+abs(Block.images_dx{i}(v(j,1),v(j,2)))/max_x;
    end
    for j=1:size(h,1)
        s1=s1+abs(Block.images_dy{i}(h(j,1),h(j,2)))/max_y;
    end
    for j=1:N2
        s2=s2+abs(Block.images_d{i}(in(j,1),in(j,2)))/max_in;
    end
    Block.s1(i)=s1/N1;
    Block.s2(i)=s2/N2;    
end
  1. Calculate S: First, since the N1 or N2 of some blocks is 0, there are NaN values ​​in the s1 and s2 matrices of Block. First, replace the value of NaN with 0: Block.s1(isnan(Block.s1))=0; Then find the mean values ​​S1 and S2 of s1 and s2, and finally find S according to the formula.
Block.s1(isnan(Block.s1))=0;
Block.s2(isnan(Block.s2))=0;
S1=mean(Block.s1);
S2=mean(Block.s2);
lambda=2;
S=abs((S1^lambda-S2^lambda)/(S1^lambda+S2^lambda));

Complete code:

I=imread('1.jpg');
if numel(size(I))>2
    I=rgb2gray(I);
end
dx=double(edge(I,'Sobel','horizontal'));
dy=double(edge(I,'Sobel','vertical'));
d=double(edge(I,'Sobel'));
lenx=8;
leny=8;
num=0;
for i=1:lenx:size(I,1)
    for j=1:leny:size(I,2)
        xend=min(i+lenx-1,size(I,1));
        yend=min(j+leny-1,size(I,2));
        num=num+1;
        Block.images_dx{num}=dx(i:xend,j:yend);
        Block.images_dy{num}=dy(i:xend,j:yend);
        Block.images_d{num}=d(i:xend,j:yend);
    end
end
Block.number=num;
for i=1:Block.number
    v=get_v(Block.images_dx{i});
    h=get_h(Block.images_dy{i});
    in=get_inner(Block.images_d{i});
    N1=size(v,1)+size(h,1);
    N2=size(in,1);
    s1=0;
    s2=0;
    max_x=max(max(Block.images_dx{i}));
    max_y=max(max(Block.images_dy{i}));
    max_in=max(max(Block.images_d{i}));
    for j=1:size(v,1)
        s1=s1+abs(Block.images_dx{i}(v(j,1),v(j,2)))/max_x;
    end
    for j=1:size(h,1)
        s1=s1+abs(Block.images_dy{i}(h(j,1),h(j,2)))/max_y;
    end
    for j=1:N2
        s2=s2+abs(Block.images_d{i}(in(j,1),in(j,2)))/max_in;
    end
    Block.s1(i)=s1/N1;
    Block.s2(i)=s2/N2;    
end
Block.s1(isnan(Block.s1))=0;
Block.s2(isnan(Block.s2))=0;
S1=mean(Block.s1);
S2=mean(Block.s2);
lambda=2;
S=abs((S1^lambda-S2^lambda)/(S1^lambda+S2^lambda));
function [vertical]=get_v(dx)
[m,n]=size(dx);
if n>=2
    vertical=zeros(2*m,2);
else
    vertical=zeros(m,2);
end
for i=1:m
    vertical(i,1)=i;
    vertical(i,2)=1;
end
if n>=2
    for i=1:m
    vertical(i+m,1)=i;
    vertical(i+m,2)=n;
    end
end
end
function [horizontal]=get_h(dy)
[m,n]=size(dy);
if m>=2
    horizontal=zeros(2*n,2);
else
    horizontal=zeros(n,2);
end
for i=1:n
    horizontal(i,1)=1;
    horizontal(i,2)=i;
end
if m>=2
    for i=1:n
    horizontal(i+n,1)=n;
    horizontal(i+n,2)=i;
    end
end
end
function [inner]=get_inner(d)
[m,n]=size(d);
inner=zeros((m-2)*(n-2),2);
k=0;
for i=2:m-1
    for j=2:n-1
        k=k+1;
        inner(k,1)=i;
        inner(k,2)=j;
    end
end
end

Guess you like

Origin blog.csdn.net/qq_36614557/article/details/102835767