欢迎关注 公众号 土盐
知乎链接:
https://zhuanlan.zhihu.com/p/76472131
眩光治疗法师登场。
待处理眩光图
grids.png
一个Matlab代码提示
How to remove the glare and brightness in an image (Image preprocessing)?
m_img = cv2.medianBlur(img,5)
ret,th1 = cv2.threshold(m_img,180,255,cv2.THRESH_BINARY)
timg = cv2.inpaint(cimg,th1,9,cv2.INPAINT_NS)
结果不美好,错误示范
这个改进失去了我想要的网格信息
这里有个提示
How to remove glare from image
但我在图像处理中找不到任何偏振滤镜实现。
任何人都可以建议任何改进,这样我可以在不丢失网格的情况下失去眩光吗?
解决方案:
C++算法大致步骤:HSV通道分离,阈值分割,再填充颜色。255判断那里是对分割后的二值图进行操作。
#include
#include
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// Load main image
Mat bgr_frame = imread("grids.png");
if (bgr_frame.empty())
{
cout << "Error loading image file" << endl;
return -1;
}
// Convert from BGR to HSV
Mat hsv_frame;
//cvtColor(bgr_frame, hsv_frame, CV_BGR2HSV);
cvtColor(bgr_frame, hsv_frame, COLOR_BGR2HSV);
// Split HSV into H, S, V channels
Mat channels[3];
split(hsv_frame, channels);
// Get mask
//threshold(channels[0], channels[0], 63, 255, CV_THRESH_BINARY);
threshold(channels[0], channels[0], 63, 255, THRESH_BINARY);
// Use mask to generate a BGR image
Mat output(channels[0].rows, channels[0].cols, CV_8UC3);
for (int j = 0; j < channels[0].rows; j++)
{
for (int i = 0; i < channels[0].cols; i++)
{
unsigned char val = channels[0].at(j, i);
if (255 == val)
{
output.at(j, i)[0] = 189;
output.at(j, i)[1] = 108;
output.at(j, i)[2] = 47;
}
else
{
output.at(j, i)[0] = 94;
output.at(j, i)[1] = 206;
output.at(j, i)[2] = 236;
}
}
}
imshow("hue", channels[0]);
imshow("output", output);
waitKey();
destroyAllWindows();
return 0;
}
自己动手实现的结果
配置环境:opencv4.0,VS2017
特别注意:
cvtColor(bgr_frame, hsv_frame, COLOR_BGR2HSV);
threshold(channels[0], channels[0], 63, 255, THRESH_BINARY);
从这个图的效果看,是对原图二值化后,填充颜色与原图近似的效果。
How to remove these small glare from the image?answers.opencv.org
python实现
import cv2
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import k_means
img = cv2.imread("./grids.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = ((img_hsv > np.array([0, 0, 230])).astype(np.float32) + (img_hsv > np.array([0, 0, 230])).astype(np.float32) * (-0.5) + 0.5)
img_partly_darken = cv2.cvtColor(mask * img_hsv, cv2.COLOR_HSV2BGR)
plt.imshow(cv2.cvtColor(img_partly_darken, cv2.COLOR_BGR2RGB))
plt.show()
cv2.imwrite("t.png", img_partly_darken)# Save the img now, and ... Surprise! You can feel the mystery:
plt.imshow(cv2.cvtColor(cv2.imread("t.png"), cv2.COLOR_BGR2RGB))
plt.show()
# Then, you can just pick out the green ones:
green_mask = img[:, :, 1] > img[:, :, 2] # value of green channel > that of red channel# Here is a trick, I use color space convertion to boardcast one channel to three channels
green_mask = (green_mask.astype(np.uint8)) * 255
green_mask = cv2.cvtColor(green_mask, cv2.COLOR_GRAY2BGR)
green3_mask = (green_mask > 0).astype(np.uint8) * 255
img_green = cv2.bitwise_and(green3_mask, img)
plt.imshow(cv2.cvtColor(img_green, cv2.COLOR_BGR2RGB))
plt.show()
# Back to the original img's colors:
ret, thr = cv2.threshold(cv2.cvtColor(img_green, cv2.COLOR_BGR2GRAY), 10, 255, cv2.THRESH_BINARY)
blue_mask = (cv2.cvtColor(thr, cv2.COLOR_GRAY2BGR) > 0).astype(np.uint8) * 255
kernel_open =cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
blue_mask = cv2.morphologyEx(blue_mask, cv2.MORPH_OPEN, kernel_open)
yellow_mask = 255 - blue_mask
# use k-means to get the two main colors -- blue and yellow
pixels = img
pixels = pixels.reshape(pixels.shape[0] * pixels.shape[1], 3)[centroids, labels, inertia] = k_means(pixels, 2)
centroids = np.array(sorted(centroids.astype(np.uint8).tolist(), key=lambda x: x[0])) # B channel
blue_centroid = centroids[1]
yellow_centroid = centroids[0]
blue_ones = cv2.bitwise_and(blue_mask, centroids[1])
yellow_ones = cv2.bitwise_and(yellow_mask, centroids[0])
plt.imshow(cv2.cvtColor(cv2.add(blue_ones, yellow_ones), cv2.COLOR_BGR2RGB))
plt.show()
https://answers.opencv.org/question/179998/how-to-remove-these-small-glare-from-the-image/answers.opencv.org