OpenCV从图像中去除眩光

Posted yantuguiguziPGJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV从图像中去除眩光相关的知识,希望对你有一定的参考价值。

欢迎关注  公众号  土盐

 

知乎链接:

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 <iostream>

#include <opencv2/opencv.hpp>

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<unsigned char>(j, i);

			if (255 == val)
			
				output.at<Vec3b>(j, i)[0] = 189;
				output.at<Vec3b>(j, i)[1] = 108;
				output.at<Vec3b>(j, i)[2] = 47;
			
			else
			
				output.at<Vec3b>(j, i)[0] = 94;
				output.at<Vec3b>(j, i)[1] = 206;
				output.at<Vec3b>(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

 

 

 

以上是关于OpenCV从图像中去除眩光的主要内容,如果未能解决你的问题,请参考以下文章

如何消除 XCode 5 / iOS 7 中的图标眩光?

sql 返回日期范围内订单的收入,转换,非眩光和抛光状态

在 Xcode 中制作 iPhone App 时,如何在手机不添加默认玻璃效果眩光的情况下制作 app 图标?

将OpenCV提取的轮廓用在另一张图中去除背景

如何使用 OpenCV 从图像中去除径向失真?

opencv 2 -- 形态学处理