You are on page 1of 14

Trắc nghiệm:

1,Thuật toán + phương pháp Canny bao gồm bao nhiêu bước : 5
2,Mục tiêu chính của việc cân bằng mức xám đó là : điều chỉnh độ tương phản
3,1/16 : Bộ lọc thông thấp
4,Thuật toán nào phù hợp nhất để loại bỏ nhiễu muối tiêu : Bộ lọc trung vị
5,Bộ lọc nào được sử dụng để tìm điểm có cường độ sáng lớn nhất trong ảnh? : Bộ
lọc cực đại
6,Ảnh nào chứa thông tin nằm ngoài sự cảm nhận của mắt người? : Ảnh nhị phân
7,Trong ảnh RGB, mỗi điểm ảnh được biểu diễn bởi : 24bit
8,Nhược điểm của bộ lọc thông thấp là : Ảnh đầu ra không sắc nét bằng ảnh
đầu vào
9, Toán tử hình thái gồm các phép toán sau: Phép co, giãn, đóng, mở
10,Những thành phần tần số cao đại diện cho dữ liệu gì trong ảnh? : Biên
11, Đầu ra của bộ lọc tuyến tính trên miền không gian được tính bởi ___________
của các điểm ảnh nằm trong miền lân cận của bộ lọc : tổng
12,Bộ lọc trung bình dựa trên cơ chế nào? : Lấy giá trị trung bình của các điểm
ảnh trong phạm vi của mặt nạ
13,Lọc sắc net dựa trên thuật toán nào? : cộng
14,Thuật ngữ nào được sử dụng khi các điểm ảnh được nhân với các hệ số khác
nhau trong phép toán lọc? : Giá trị trung bình có trọng số (weighted average)
15,Đạo hàm bậc hai còn được gọi là : Laplace
16, Nhược điểm của bộ lọc trung bình là gì : làm mờ ảnh
17, Phép toán nào được thực hiện nhằm tăng cường độ sắc nét của ảnh? : Tích
phân
18, Nhiệm vụ của bộ lọc trong xử lý ảnh số là : loại bỏ nhiễu, phát hiện biên,
nâng cao chất lượng ảnh
19, Lược đồ mức xám của một ảnh số có các mức xám nằm trong khoảng [0,L-1]
được tính bởi công thức? (Trong đó, nk là số điểm ảnh có mức xám rk; n là tổng
số điểm ảnh) : h(rk) = nk
20,Mục tiêu của việc cân bằng Histogram là ____________ :Tăng cường độ
tương phản trong ảnh
21,Trong các kỹ thuật sau, đâu là các bước của xử lý ảnh? : Lấy mẫu, Xử lý tín
hiệu số (DSP), Khôi phục ảnh
22,Đạo hàm bậc nhất còn được gọi là :"Gradient".
23, Trong ảnh xám gồm 256 mức khác nhau, cần sử dụng bao nhiêu bit để biểu
diễn một điểm ảnh? : 8bit
24,Mục tiêu của ảnh vi phân là làm rõ đối tượng nào sau đây? : Biên ảnh
25,Toán tử Sobel được sử dụng trong bài toán tách biên dựa trên cơ chế nào? :
Đạo hàm bậc nhất
26,Phép nào sau đây thuộc toán tử hình thái? : Phép co
27, Bộ lọc nào được thực hiện trong miền tần số tương đương với bộ lọc thông
thấp trong miền không gian? : Gauss
28, Bộ lọc trung bình còn được gọi là : "Bộ lọc thông thấp"
29, Ảnh nào sau đây sử dụng các giá trị 0 và 1 trong biểu diễn ảnh? : nhị phân
30,Mặt nạ được biểu diễn bởi ma trận sau được gọi là bộ lọc gì? : Bộ lọc trung
bình
CODE:
Bài 1: chuyển sang ảnh xám
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread("ro.jpg")
print("Kich thuoc cua anh goc la: ", img.shape)
B, G, R = img[:,:,0], img[:,:,1], img[:,:,2]
img_gray = 0.2989 * R + 0.5870 * G + 0.1140 * B

plt.subplot(121)
plt.imshow(img[:,:,::-1])
plt.title("anh goc")

plt.subplot(122)
plt.imshow(img_gray, cmap = "gray")
plt.title("anh mau xam")

plt.show()

Bài 2.1: histogram- cân bằng- sau cân bằng


import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
matplotlib.rc('xtick', labelsize=8)
matplotlib.rc('ytick', labelsize=8)

img = cv2.imread("a.jpg")
plt.subplot(221)
plt.imshow(img[:,:,::-1])
plt.title("Ảnh gốc")
plt.subplot(222)
plt.hist(img.ravel(),256,[0,256])
plt.title("Histogram ảnh gốc")
plt.subplot(223)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img1 = cv2.equalizeHist(gray)
plt.imshow(img1,cmap = 'gray')
plt.xlabel("Ảnh cân bằng Histogram")
plt.subplot(224)
plt.hist(img1.ravel(),256,[0,256])
plt.xlabel('Histogram sau cân bằng')
Bài 2.2: âm bản-log-mũ

import cv2
import numpy as np
import math
from matplotlib import pyplot as plt

img = cv2.imread("ro.jpg")
#print("Kich thuoc cua anh goc la: ", img.shape)
img_gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY)

plt.subplot(221)
plt.imshow(img_gray, cmap = "gray")
plt.title("ảnh mức xám")

plt.subplot(222)
img_amban = 255 - img_gray
plt.imshow(img_amban, cmap = "gray")
plt.title("ảnh âm bản")

plt.subplot(223)
img_log = 2*(np.log(1 + img_gray)) #c*log(1+f(m,n))
plt.imshow(img_log, cmap = "gray")
plt.title("ảnh log")

plt.subplot(224)
img_mu = 2*img_gray #c*f(m,n)
plt.imshow(img_mu, cmap = "gray")
plt.title("ảnh mũ")

plt.show()

Bài 3: thêm nhiễu- lọc nhiễu


import random
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc('xtick', labelsize=0)
matplotlib.rc('ytick', labelsize=0)

imgq = cv2.imread('a.jpg')
img_gray = cv2.cvtColor(imgq,cv2.COLOR_BGR2GRAY) #ảnh xám
def gauss(image, mean=0, sigma=20): #hàm nhiễu Gauss mean: kì vọng,
#sigma: độ lệch chuẩn,phương sai = sigma^2
gaussian_noise = np.random.normal(mean, sigma, image.shape) #tạo nhiễu
gauss
gaussian_noise = gaussian_noise.reshape(image.shape) #reshape: sap xep cac
gia tri theo ma tran như ý muốn
noisy_image = image + gaussian_noise
noisy_image = np.clip(noisy_image, 0, 255)# nếu cộng vào nhiễu <0 hoặc >255
thì đưa veeg giá trị min = 0 hoặc max = 255,và ngược lại
noisy_image = noisy_image.astype(np.uint8)#chuyển về dạng dữ liệu số nguyên
0 dấu 8 bit
return noisy_image
img_gauss = gauss(img_gray)
def muoitieu(img): #hàm nhiễu Muối tiêu

# Lấy kích thước của hình ảnh


r , c = img.shape

# Chọn ngẫu nhiên một số pixel trong ảnh để tô màu chúng thành màu trắng
# Chọn một số ngẫu nhiên trong khoảng từ 300 đến 10000
number_of_pixels = random.randint(300, 10000)
for i in range(number_of_pixels):

# Chọn một tọa độ x ngẫu nhiên


x_coord=random.randint(0, r - 1)

# Chọn một tọa độ y ngẫu nhiên


y_coord=random.randint(0, c - 1)

# Tô màu pixel đó thành màu trắng


img[x_coord][y_coord] = 255

# Chọn ngẫu nhiên một số pixel trong ảnh để tô màu đen cho chúng
# Chọn một số ngẫu nhiên trong khoảng từ 300 đến 10000
number_of_pixels = random.randint(300 , 10000)#chọn tọa độ ngẫu nhiên
for i in range(number_of_pixels):

# Chọn một tọa độ x ngẫu nhiên


x_coord=random.randint(0, r - 1)

# Chọn một tọa độ y ngẫu nhiên


y_coord=random.randint(0, c - 1)

# Tô màu pixel đó thành màu đen


img[x_coord][y_coord] = 0
return img
#Ảnh gốc
plt.subplot(231)
plt.imshow(imgq[:,:,::-1])
plt.title("Ảnh gốc")
#Ảnh nhiễu muối tiêu
img_muoitieu = muoitieu(img_gray)
plt.subplot(232)
plt.imshow(img_muoitieu,cmap = 'gray')
plt.title("Nhiễu Muối tiêu")
#Ảnh nhiễu Gauss
plt.subplot(233)
plt.imshow(img_gauss,cmap = 'gray')
plt.title("Nhiễu Gauss")
#Ảnh nhiễu Poisson
img_poisson = np.random.poisson(img_gray, size=None)
plt.subplot(234)
plt.imshow(img_poisson,cmap = 'gray')
plt.xlabel("Nhiễu Poisson")
# Obtain number of rows and columns
# of the image
#lọc trung bình
img = img_muoitieu #lọc ảnh bị nhiễu muối tiêu
m, n = img.shape

# Develop Averaging filter(3, 3) mask


mask = np.ones([3, 3], dtype = int)
mask = mask / 9

# Convolve the 3X3 mask over the image


img_new = np.zeros([m, n])

for i in range(1, m-1):


for j in range(1, n-1):
temp = img[i-1, j-1]*mask[0, 0]+img[i-1, j]*mask[0, 1]+img[i-1, j +
1]*mask[0, 2]+img[i, j-1]*mask[1, 0]+ img[i, j]*mask[1, 1]+img[i, j + 1]*mask[1,
2]+img[i + 1, j-1]*mask[2, 0]+img[i + 1, j]*mask[2, 1]+img[i + 1, j + 1]*mask[2,
2]

img_new[i, j]= temp


plt.subplot(235)
img_new = img_new.astype(np.uint8)
plt.imshow(img_new,cmap = 'gray')
plt.xlabel("Lọc trung bình")

#loc trung vị
m, n = img.shape
# Di chuyển hình ảnh. Đối với mỗi khu vực 3X3,
# tìm trung vị của các pixel và
# thay thế pixel trung tâm bằng trung vị
img_new1 = np.zeros([m, n])

for i in range(1, m-1):


for j in range(1, n-1):
temp = [img[i-1, j-1],
img[i-1, j],
img[i-1, j + 1],
img[i, j-1],
img[i, j],
img[i, j + 1],
img[i + 1, j-1],
img[i + 1, j],
img[i + 1, j + 1]]

temp = sorted(temp)
img_new1[i, j]= temp[4]
plt.subplot(236)
img_new1 = img_new1.astype(np.uint8)
plt.imshow(img_new1,cmap = 'gray')
plt.xlabel("Lọc trung vị")
plt.show()

Bài 4: toán tử
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
matplotlib.rc('xtick', labelsize=0)
matplotlib.rc('ytick', labelsize=0)

img = cv2.imread('ro.jpg')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

w = img.shape[1]
h = img.shape[0]

def convert_RGB_GRAY(img):
return np.dot(img[:,:,:3],[0.299, 0.587, 0.144])

def tach_bien(h,w,img,maskx,masky):
img_new = np.zeros([h, w])
for i in range(1,h-1):
for j in range(1,w-1):

temp = img[i-1:i+2,j-1:j+2]
gx = np.sum(temp*maskx)
gy = np.sum(temp*masky)
img_new[i,j] = (gx**2 + gy ** 2)**(1/2)
return img_new

def kirsch(h,w,img,mask):
sum_array = []
for i in range(1,h-1):
for j in range(1,w-1):
for m in range(len(mask)):
temp = img[i - 1:i + 2, j - 1:j + 2]
sum_array.append(np.sum(temp*mask[m]))
img[i,j] = max(sum_array)
sum_array.clear()
return img

def robert(h,w,img,maskx,masky):
img_new = np.zeros([h, w])
for i in range(1, h - 1):
for j in range(1, w - 1):
temp = img[i - 1:i + 1, j - 1:j + 1]
gx = np.sum(temp * maskx)
gy = np.sum(temp * masky)
img_new[i, j] = (gx ** 2 + gy ** 2) ** (1 / 2)
return img_new

prewitt_x = np.array(([-1,0,1],[-1,0,1],[-1,0,1]))
prewitt_y = np.array(([-1,-1,-1],[0,0,0],[1,1,1]))

sobel_x = np.array(([-1,0,1],[-2,0,2],[-1,0,1]))
sobel_y = np.array(([-1,-2,-1],[0,0,0],[1,2,1]))

robert_x = np.array(([1,0],[0,-1]))
robert_y = np.array(([0,1],[-1,0]))

mask = []
kirsch_1 = np.array(([5,5,5],[-3,0,-3],[-3,-3,-3]))
mask.append(kirsch_1)
kirsch_2 = np.array(([-3,5,5],[-3,0,5],[-3,-3,-3]))
mask.append(kirsch_2)
kirsch_3 = np.array(([-3,-3,5],[-3,0,5],[-3,-3,5]))
mask.append(kirsch_3)
kirsch_4 = np.array(([-3,-3,-3],[-3,0,5],[-3,5,5]))
mask.append(kirsch_4)
kirsch_5 = np.array(([-3,-3,-3],[-3,0,-3],[5,5,5]))
mask.append(kirsch_5)
kirsch_6 = np.array(([-3,-3,-3],[5,0,-3],[5,5,-3]))
mask.append(kirsch_6)
kirsch_7 = np.array(([5,-3,-3],[5,0,-3],[5,-3,-3]))
mask.append(kirsch_7)
kirsch_8 = np.array(([5,5,-3],[5,0,-3],[-3,-3,-3]))
mask.append(kirsch_8)

gray = convert_RGB_GRAY(img)
plt.subplot(2,3,1)
plt.imshow(img)
plt.title("Ảnh gốc")

plt.subplot(2,3,2)
plt.imshow(gray,cmap='gray')
plt.title("Ảnh Gray")

img_sobel = tach_bien(h,w,gray,sobel_x,sobel_y)
plt.subplot(2,3,3)
plt.imshow(img_sobel,cmap='gray')
plt.title("Toán tử sobel")

img_prewitt = tach_bien(h,w,gray,prewitt_x,prewitt_y)
plt.subplot(2,3,4)
plt.imshow(img_prewitt,cmap='gray')
plt.title("Toán tử prewitt")

img_robert = robert(h,w,gray,robert_x,robert_y)
plt.subplot(2,3,5)
plt.imshow(img_robert,cmap='gray')
plt.title("Toán tử robert")

img_kirsch = kirsch(h,w,img,mask)
plt.subplot(2,3,6)
plt.imshow(img_kirsch,cmap='gray')
plt.title("Toán tử kirsch")

plt.show()

Bài 5: Canny
import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib

matplotlib.rc('xtick', labelsize=0)
matplotlib.rc('ytick', labelsize=0)

img = cv2.imread('a.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

w = img.shape[1]
h = img.shape[0]

gaussq = np.array([[2, 4, 5, 4, 2],


[4, 9, 12, 9, 4],
[5, 12, 15, 12, 5],
[4, 9, 12, 9, 4],
[2, 4, 5, 4, 2]]) / 159

# Hàm tích chập


def convolveq(image, kernel):
# Lấy kích thước ảnh và kernel
img_h, img_w = image.shape
kernel_h, kernel_w = kernel.shape

# Tạo ma trận kết quả


img_new = np.zeros((img_h - kernel_h + 1, img_w - kernel_w + 1))

# Áp dụng tích chập


for i in range(img_new.shape[0]):
for j in range(img_new.shape[1]):
img_new[i, j] = np.sum(image[i:i+kernel_h, j:j+kernel_w] * kernel)

return img_new

def sobel_convolveq(image):
# Khởi tạo ma trận Sobel theo hướng ngang và hướng dọc
sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])

# Tạo ma trận kết quả


result_x = np.zeros_like(image)
result_y = np.zeros_like(image)

# Áp dụng tích chập với ma trận Sobel


for i in range(1, image.shape[0]-1):
for j in range(1, image.shape[1]-1):
gx = np.sum(sobel_x * image[i-1:i+2, j-1:j+2])
gy = np.sum(sobel_y * image[i-1:i+2, j-1:j+2])
result_x[i, j] = gx
result_y[i, j] = gy

# Tính toán độ lớn và hướng của gradient


G = np.sqrt(result_x**2 + result_y**2)
theta = np.arctan2(result_y, result_x)

return G, theta
def nonq_max_suppression(img, D): #xóa điểm biên không phải cực đại
M,N = img.shape
Z = np.zeros((M,N), dtype=np.int32)
goc = D * 180. / np.pi
goc[goc < 0] += 180

for i in range(1,M-1):
for j in range(1,N-1):
#angle 0
if (0 <= goc[i,j] < 22.5) or (157.5 <= goc[i,j] <= 180):
q = img[i, j+1]
r = img[i, j-1]
#angle 45
elif (22.5 <= goc[i,j] < 67.5):
q = img[i+1, j-1]
r = img[i-1, j+1]
#angle 90
elif (67.5 <= goc[i,j] < 112.5):
q = img[i+1, j]
r = img[i-1, j]
#angle 135
elif (112.5 <= goc[i,j] < 157.5):
q = img[i-1, j-1]
r = img[i+1, j+1]

if (img[i,j] >= q) and (img[i,j] >= r):


Z[i,j] = img[i,j]
else:
Z[i,j] = 0
return Z

def thresholdq(img, lowThreshold=0.05, highThreshold= 0.15): # phân loại điểm


biên theo ngưỡng
High = img.max() * highThreshold
Low = highThreshold * lowThreshold

M, N = img.shape
res = np.zeros((M,N), dtype=np.int32)

weak = np.int32(75)
strong = np.int32(255)

strong_i, strong_j = np.where(img >= High)


zeros_i, zeros_j = np.where(img < Low)

weak_i, weak_j = np.where((img <= highThreshold) & (img >=


lowThreshold))

res[strong_i, strong_j] = strong


res[weak_i, weak_j] = weak

return res
def hysteresisq(img):# kết nối các điểm biên mờ

M, N = img.shape
weak = 75
strong = 255
for i in range(1, M-1):
for j in range(1, N-1):
if (img[i,j] == weak):
if ((img[i+1, j-1] == strong)
or (img[i+1, j] == strong)
or (img[i+1, j+1] == strong)
or (img[i, j-1] == strong)
or (img[i, j+1] == strong)
or (img[i-1, j-1] == strong)
or (img[i-1, j] == strong)
or (img[i-1, j+1] == strong)):
img[i, j] = strong
else:
img[i, j] = 0

return img

smooth_img = convolveq(img_gray,gaussq)

gradientMat,thetaMat = sobel_convolveq(smooth_img)

nonMaxImg = nonq_max_suppression(gradientMat, thetaMat)

thresholdImg = thresholdq(nonMaxImg)

img_final = hysteresisq(thresholdImg)

plt.subplot(131)
plt.imshow(img[:,:,::-1])
plt.title("Ảnh gốc")

plt.subplot(132)
plt.imshow(img_gray,cmap ='gray')
plt.title("Ảnh Xám")

plt.subplot(133)
plt.imshow(img_final,cmap = 'gray')
plt.title("Ảnh Canny")

plt.show()

Bài 6: distance transform


import cv2
import numpy as np
from matplotlib import pyplot as plt
import matplotlib
img = cv2.imread('a.jpg')
# Convert image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Convert grayscale image to uint8


gray = np.uint8(gray)

# Threshold image to create binary image


ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

def distanceTransform(img):
# Tạo ma trận distance trống
distance = np.zeros_like(img, dtype=np.float32)
# Kích thước ảnh
h, w = img.shape[:2]

# Duyệt qua từng điểm ảnh và tính toán khoảng cách


for y in range(h):
for x in range(w):
# Nếu điểm ảnh là điểm ảnh trắng
if img[y, x] > 0:
continue
# Tính toán khoảng cách từ điểm ảnh đến các điểm ảnh trắng gần nhất
distances = np.sqrt((np.arange(h)[:, None] - y) ** 2 + (np.arange(w) - x) **
2)
# Chọn khoảng cách nhỏ nhất
dist_min = np.min(distances[img > 0])
# Gán khoảng cách vào ma trận distance
distance[y, x] = dist_min

return distance

def erode(dist_transform, kernel_size=3, iterations=5):


# Tách khung xương từ ảnh distanceTransform bằng kỹ thuật ăn mòn ảnh
kernel = np.ones((kernel_size, kernel_size), np.uint8)
skeleton = cv2.erode(dist_transform, kernel, iterations=iterations)
return skeleton

dt = distanceTransform(binary)
end = erode(dt)

plt.subplot(231)
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
plt.title("Ảnh gốc")

plt.subplot(232)
plt.imshow(binary,cmap = 'gray')
plt.xlabel("Ảnh nhị phân")

plt.subplot(233)
plt.imshow(dt,cmap = 'gray')
plt.title("Ảnh distanceTransform")

plt.subplot(235)
plt.imshow(end,cmap = 'gray')
plt.title("Ảnh tách khung xương")

ĐỀ 16
Chuyển từ RGB sang YCbCr
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread("ro.jpg")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #ảnh xám
print("Kích thước của ảnh gốc là:", img.shape)

def convert_to_ycbcr(image):
R, G, B = image[:, :, 0], image[:, :, 1], image[:, :, 2]
Y = 16 + (219 * (0.299 * R + 0.587 * G + 0.114 * B) / 255)
Cb = 128 + (224 * (-0.169 * R - 0.331 * G + 0.5 * B) / 255)
Cr = 128 + (224 * (0.5 * R - 0.419 * G - 0.081 * B) / 255)
return Y, Cb, Cr

Y, Cb, Cr = convert_to_ycbcr(img)

plt.subplot(131)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_RGB2YCrCb))
plt.title("anh ycbcr")

def gauss(image, mean=0, sigma=20): #hàm nhiễu Gauss mean: kì vọng,


#sigma: độ lệch chuẩn,phương sai = sigma^2
gaussian_noise = np.random.normal(mean, sigma, image.shape) #tạo nhiễu
gauss
gaussian_noise = gaussian_noise.reshape(image.shape) #reshape: sap xep cac
gia tri theo ma tran như ý muốn
noisy_image = image + gaussian_noise
noisy_image = np.clip(noisy_image, 0, 255)# nếu cộng vào nhiễu <0 hoặc >255
thì đưa veeg giá trị min = 0 hoặc max = 255,và ngược lại
noisy_image = noisy_image.astype(np.uint8)#chuyển về dạng dữ liệu số nguyên
0 dấu 8 bit
return noisy_image
img_gauss = gauss(img_gray)
plt.subplot(132)
plt.imshow(img_gauss,cmap = 'gray')
plt.title("anh gauss")
m, n = img.shape
# Di chuyển hình ảnh. Đối với mỗi khu vực 3X3,
# tìm trung vị của các pixel và
# thay thế pixel trung tâm bằng trung vị
img_new1 = np.zeros([m, n])

for i in range(1, m-1):


for j in range(1, n-1):
temp = [img[i-1, j-1],
img[i-1, j],
img[i-1, j + 1],
img[i, j-1],
img[i, j],
img[i, j + 1],
img[i + 1, j-1],
img[i + 1, j],
img[i + 1, j + 1]]

temp = sorted(temp)
img_new1[i, j]= temp[4]
plt.subplot(133)
img_new1 = img_new1.astype(np.uint8)
plt.imshow(img_new1,cmap = 'gray')
plt.xlabel("Lọc trung vị")
plt.show()

You might also like