Sag*_*gRU 5 python opencv image image-processing python-3.x
我通过 Python 3.7 使用 OpenCV。我有一组单色图像,如下所示:
我想找到这些图像上的所有“关节点”,其中“关节点”是两块木板每个交叉点的中心(1 像素)。这些“关节”大致由下图中的红色圆圈表示:
第一个想法是对图像进行骨架化,然后通过算法找到所有连接的边缘,但所有骨架化技术都给了我摆动或圆角和额外的“芽”。
import cv2
import numpy as np
from skimage.morphology import skeletonize
image = cv2.imread("SOURCE_IMAGE.jpg", cv2.IMREAD_GRAYSCALE)
binary_image = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 91, 12)
skeleton = (skeletonize(binary_image//255) * 255).astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)
结果:
第二个想法是找到内部轮廓,将它们近似为边界点,找到最近的邻居,然后以某种方式计算中心,但是,再一次,Canny 边缘检测方法给了我摆动的角和额外的点。
import cv2
image = cv2.imread("SOURCE_IMAGE.jpg", cv2.IMREAD_GRAYSCALE)
edged = cv2.Canny(image, 100, 200)
Run Code Online (Sandbox Code Playgroud)
结果:
有没有可靠的方法来解决这个问题?
这是我解决这个问题的方法:
第一步检查每一列并确定细线并将其设为黑色 (0)。结果将只是垂直线。第二步做反向操作。最后将垂直线图像与水平线图像进行比较。两者中白色的像素 (255) 是交点。
注意:请不要因为用 C++ 编码而责怪我。我对 python 不熟悉,我只是想展示我的方法和结果。
这是代码和结果:
来源:
垂直线:
水平线:
结果:
代码:
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
Mat img = imread("/ur/image/directory/joints.jpg",1);
imshow("Source",img);
int checker = 1,checker2 = 1;
int begin_y,finish_y2,finish_y,begin_y2;
Mat vertical_img = img.clone();
Mat horizontal_img = img.clone();
cvtColor(vertical_img,vertical_img,CV_BGR2GRAY);
cvtColor(horizontal_img,horizontal_img,CV_BGR2GRAY);
int finish_checker = 0,finish_checker2=0;
for(int i=0;i<horizontal_img.rows;i++)
{
for(int j=0;j<horizontal_img.cols;j++)
{
if(horizontal_img.at<uchar>(Point(j,i))>100 && checker)
{
begin_y = j;
checker = 0;
}
if(horizontal_img.at<uchar>(Point(j,i))<20 && checker==0)
{
finish_y = j;
checker = 1;
finish_checker = 1;
}
if(finish_checker)
{
if((finish_y-begin_y)<30)
{
for(int h=begin_y-2;h<=finish_y;h++)
{
horizontal_img.at<uchar>(Point(h,i)) = 0;
}
}
finish_checker = 0;
}
}
}
imshow("Horizontal",horizontal_img);
for(int i=0;i<vertical_img.cols;i++)
{
for(int j=0;j<vertical_img.rows;j++)
{
if(vertical_img.at<uchar>(Point(i,j))>100 && checker2)
{
begin_y2 = j;
checker2 = 0;
}
if(vertical_img.at<uchar>(Point(i,j))<50 && checker2==0)
{
finish_y2 = j;
checker2 = 1;
finish_checker2 = 1;
}
if(finish_checker2)
{
if((finish_y2-begin_y2)<30)
{
for(int h=begin_y2-2;h<=finish_y2;h++)
{
vertical_img.at<uchar>(Point(i,h)) = 0;
}
}
finish_checker2 = 0;
}
}
}
imshow("Vertical",vertical_img);
for(int y=0;y<img.cols;y++)
{
for(int z=0;z<img.rows;z++)
{
if(vertical_img.at<uchar>(Point(y,z))>200 && horizontal_img.at<uchar>(Point(y,z))>200)
{
img.at<cv::Vec3b>(z,y)[0]=0;
img.at<cv::Vec3b>(z,y)[1]=0;
img.at<cv::Vec3b>(z,y)[2]=255;
}
}
}
imshow("Result",img);
waitKey(0);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是@YunusTemurlenk 的方法的稍微修改版本,使用 Python 而不是 C++。这个想法是:
获取水平和垂直线掩模。创建水平和垂直结构元素,cv2.getStructuringElement然后执行cv2.morphologyEx隔离线条。
寻找关节。我们将cv2.bitwise_and两个面具放在一起以获得接头。
水平/垂直线掩模

检测到的接头呈绿色
结果
import cv2
import numpy as np
# Load image, grayscale, Gaussian blur, Otsus threshold
image = cv2.imread('1.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# Find horizonal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10,1))
horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
# Find vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,10))
vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
# Find joints
joints = cv2.bitwise_and(horizontal, vertical)
# Find centroid of the joints
cnts = cv2.findContours(joints, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
# Find centroid and draw center point
M = cv2.moments(c)
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
cv2.circle(image, (cx, cy), 3, (36,255,12), -1)
cv2.imshow('thresh', thresh)
cv2.imshow('horizontal', horizontal)
cv2.imshow('vertical', vertical)
cv2.imshow('joints', joints)
cv2.imshow('image', image)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1855 次 |
| 最近记录: |